### Install FikenPy Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Install the FikenPy library using pip. This command installs directly from the GitHub repository. ```bash pip install git+https://github.com/gronnmann/fiken-py ``` -------------------------------- ### Clone Repository and Install Dependencies Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Clone the fikenpy repository and install development dependencies using uv. This command ensures all extra dependencies required for development are included. ```bash git clone https://github.com/gronnmann/fikenpy.git cd fikenpy # Install with dev dependencies uv sync --all-extras ``` -------------------------------- ### FikenPy Sync Client: Get User and Companies Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Demonstrates how to retrieve user information and a list of companies using the synchronous FikenClient. ```python # Get user info user = client.get_user() # Get all companies for company in client.get_companies(): print(company.name) ``` -------------------------------- ### FikenPy Authentication with API Token Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Example of initializing the FikenClient using an API token. This method is recommended for personal usage. ```python client = FikenClient(api_token="your_api_token") ``` -------------------------------- ### FikenPy Authentication with OAuth2 Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Example of initializing the FikenClient with OAuth2 credentials. The client automatically handles token refresh. ```python client = FikenClient( access_token="your_access_token", refresh_token="your_refresh_token", client_id="your_client_id", client_secret="your_client_secret" ) ``` -------------------------------- ### FikenPy Sync Client: Create a New Contact Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Example of creating a new contact for a company using the synchronous FikenClient. Requires company slug and ContactRequest data. ```python # Create a new contact new_contact = client.create_contact( company_slug="my-company", data=ContactRequest( name="John Doe", email="john@example.com", customer=True ) ) ``` -------------------------------- ### Get Companies Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Retrieve a list of all companies accessible by the authenticated user. ```APIDOC ## Get Companies ### Description Retrieve a list of all companies accessible by the authenticated user. ### Method (Sync) ```python client.get_companies() ``` ### Method (Async) ```python await client.get_companies() ``` ``` -------------------------------- ### FikenPy Async Client: Get Contacts for a Company Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Shows how to asynchronously retrieve contacts for a specific company using the AsyncFikenClient. Requires company slug. ```python # Get contacts for a company contacts = await client.get_contacts(company_slug="my-company") async for contact in contacts: print(contact.name) ``` -------------------------------- ### Get User Info Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Retrieve information about the authenticated user. ```APIDOC ## Get User Info ### Description Retrieve information about the authenticated user. ### Method (Sync) ```python client.get_user() ``` ### Method (Async) ```python await client.get_user() ``` ``` -------------------------------- ### Get Contacts Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Retrieve a list of contacts for a specific company. ```APIDOC ## Get Contacts ### Description Retrieve a list of contacts for a specific company. ### Parameters #### Path Parameters - **company_slug** (string) - Required - The unique identifier for the company. ### Method (Sync) ```python client.get_contacts(company_slug="my-company") ``` ### Method (Async) ```python await client.get_contacts(company_slug="my-company") ``` ``` -------------------------------- ### Get User Information Source: https://context7.com/gronnmann/fikenpy/llms.txt Retrieves information about the authenticated user using the `get_user()` method. The response is a `Userinfo` Pydantic model. ```APIDOC ## User `get_user()` — retrieve information about the authenticated user. Returns a `Userinfo` Pydantic model containing the user's name, email, and associated company details. ```python from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: user = client.get_user() # Userinfo fields: name, email, ... print(f"Logged in as: {user.name} ({user.email})") ``` ``` -------------------------------- ### Client Initialization Source: https://context7.com/gronnmann/fikenpy/llms.txt Demonstrates how to create synchronous and asynchronous Fiken clients using either an API token or OAuth2 credentials. It also shows how to use the client as a context manager. ```APIDOC ## Client Initialization `FikenClient` / `AsyncFikenClient` — create a sync or async client with API-token or OAuth2 credentials. Both clients accept the same keyword arguments: `api_token`, or the four OAuth2 parameters (`access_token`, `refresh_token`, `client_id`, `client_secret`). An optional `base_url` and `timeout` are also accepted. Exactly one authentication strategy must be supplied; omitting both raises `ValueError`. ```python from fikenpy import FikenClient, AsyncFikenClient # --- Sync: API token --- client = FikenClient(api_token="YOUR_API_TOKEN") # --- Sync: OAuth2 --- client = FikenClient( access_token="ACCESS", refresh_token="REFRESH", client_id="CLIENT_ID", client_secret="CLIENT_SECRET", ) # Use as a context manager (ensures the underlying httpx.Client is closed) with FikenClient(api_token="YOUR_API_TOKEN") as client: user = client.get_user() print(user.name) # --- Async: API token --- import asyncio async def main() -> None: async with AsyncFikenClient(api_token="YOUR_API_TOKEN") as client: user = await client.get_user() print(user.name) asyncio.run(main()) ``` ``` -------------------------------- ### Initialize FikenPy Client (Sync/Async) Source: https://context7.com/gronnmann/fikenpy/llms.txt Demonstrates creating synchronous and asynchronous Fiken clients using either an API token or OAuth2 credentials. The client can be used as a context manager to ensure resources are properly closed. ```python from fikenpy import FikenClient, AsyncFikenClient # --- Sync: API token --- client = FikenClient(api_token="YOUR_API_TOKEN") # --- Sync: OAuth2 --- client = FikenClient( access_token="ACCESS", refresh_token="REFRESH", client_id="CLIENT_ID", client_secret="CLIENT_SECRET", ) # Use as a context manager (ensures the underlying httpx.Client is closed) with FikenClient(api_token="YOUR_API_TOKEN") as client: user = client.get_user() print(user.name) # --- Async: API token --- import asyncio async def main() -> None: async with AsyncFikenClient(api_token="YOUR_API_TOKEN") as client: user = await client.get_user() print(user.name) asyncio.run(main()) ``` -------------------------------- ### Initialize FikenPy Async Client Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Initialize the asynchronous FikenClient using an API token. Use 'async with' for proper resource management. ```python from fikenpy import AsyncFikenClient async with AsyncFikenClient(api_token="your_api_token") as client: # Get user info user = await client.get_user() ``` -------------------------------- ### Initialize FikenPy Sync Client with API Token Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Initialize the synchronous FikenClient using an API token. This is recommended for personal use. ```python from fikenpy import FikenClient # Using API token client = FikenClient(api_token="your_api_token") ``` -------------------------------- ### Async Client Initialization Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Initialize the asynchronous Fiken client using either an API token or OAuth2 credentials. ```APIDOC ## Async Client Initialization ### Description Initialize the asynchronous Fiken client using either an API token or OAuth2 credentials. ### Method ```python async with AsyncFikenClient(api_token="your_api_token") as client: ... ``` ``` -------------------------------- ### List and Fetch Companies Source: https://context7.com/gronnmann/fikenpy/llms.txt Demonstrates how to list all associated companies using `get_companies()` with automatic pagination, and how to fetch a specific company by its slug using `get_company()`. ```python from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: # Iterate all companies (automatic pagination) for company in client.get_companies(): print(company.slug, company.name) # Fetch a single company by slug company = client.get_company("my-company-as") print(company.organizationNumber) ``` -------------------------------- ### Create and List Sales Source: https://context7.com/gronnmann/fikenpy/llms.txt This code snippet demonstrates how to record direct sales (cash or card) and list existing sales. Ensure the `SaleRequest` includes all necessary details like date, kind, currency, lines, and payment information. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import SaleRequest, SaleLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") sale = co.create_sale(SaleRequest( date=date(2024, 6, 15), kind="CASH_SALE", currency="NOK", lines=[ SaleLine( description="Online sale", unitPrice=299_00, quantity=3, vatType="HIGH", incomeAccount="3000", ) ], paymentDate=date(2024, 6, 15), paymentAccount="1920:10001", )) print(f"Sale ID: {sale.saleId}") for s in co.get_sales(): print(s.saleId, s.date, s.totalPaid) ``` -------------------------------- ### Sync Client Initialization Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Initialize the synchronous Fiken client using either an API token or OAuth2 credentials. ```APIDOC ## Sync Client Initialization ### Description Initialize the synchronous Fiken client using either an API token or OAuth2 credentials. ### Method ```python FikenClient(api_token="your_api_token") ``` ### Method ```python FikenClient( access_token="your_access_token", refresh_token="your_refresh_token", client_id="your_client_id", client_secret="your_client_secret" ) ``` ``` -------------------------------- ### Async Client Usage with FikenPy Source: https://context7.com/gronnmann/fikenpy/llms.txt Demonstrates asynchronous iteration over contacts and creation of an invoice using AsyncFikenClient. Ensure you have the necessary API token and company identifier. ```python import asyncio from datetime import date from fikenpy import AsyncFikenClient from fikenpy.models import InvoiceRequest, InvoiceLine, Contact async def main() -> None: async with AsyncFikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Iterate contacts asynchronously async for contact in co.get_contacts(customer=True): print(contact.name) # Create invoice asynchronously invoice = await co.create_invoice(InvoiceRequest( issueDate=date(2024, 8, 1), dueDate=date(2024, 8, 31), customerId=42, lines=[InvoiceLine( description="August retainer", unitPrice=2000_00, quantity=1, vatType="HIGH", incomeAccount="3000", )], )) print(f"Invoice #{invoice.invoiceNumber}") asyncio.run(main()) ``` -------------------------------- ### Initialize Scoped FikenPy Client Source: https://context7.com/gronnmann/fikenpy/llms.txt Shows how to create a company-scoped Fiken client, which pre-fills the company slug for all subsequent operations. This simplifies calls when working with a single company. ```python from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # No need to pass company_slug any more for contact in co.get_contacts(): print(contact.name) for invoice in co.get_invoices(): print(invoice.invoiceNumber, invoice.net) for product in co.get_products(): print(product.name, product.unitPrice) ``` -------------------------------- ### Manage Bank Accounts and Balances Source: https://context7.com/gronnmann/fikenpy/llms.txt Register new bank accounts, list active accounts, and retrieve bank balances. Ensure you provide correct bank details. ```python from fikenpy import FikenClient from fikenpy.models import BankAccountRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Register a new bank account bank_acc = co.create_bank_account(BankAccountRequest( name="Main operating account", bankAccountNumber="12345678901", bic="DNBANOKKXXX", iban="NO9386011117947", foreignService=False, )) print(f"Bank account ID: {bank_acc.bankAccountId}") # List all active bank accounts for ba in co.get_bank_accounts(inactive=False): print(ba.bankAccountId, ba.name, ba.bankAccountNumber) # Bank balances for bb in co.get_bank_balances(): print(bb.bankAccountId, bb.balance) ``` -------------------------------- ### Create Sale Draft and Sale Source: https://context7.com/gronnmann/fikenpy/llms.txt Creates a draft sale and then converts it into a final sale. Useful for complex sales requiring multiple steps. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import DraftRequest, DraftLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") draft = co.create_sale_draft(DraftRequest( date=date(2024, 7, 5), type="CASH_SALE", currency="NOK", lines=[DraftLine( description="Workshop fee", unitPrice=500_00, quantity=2, vatType="HIGH", account="3000", )], )) sale = co.create_sale_from_draft(draft.draftId) print(f"Sale ID: {sale.saleId}") ``` -------------------------------- ### Manage Products in Python Source: https://context7.com/gronnmann/fikenpy/llms.txt Provides full CRUD operations for products and services. The `Product` model includes name, unit price, income account, VAT type, and status. Use `get_products(active=True)` to list active products. ```python from fikenpy import FikenClient from fikenpy.models import Product with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Create a product product = co.create_product(Product( name="Consulting Hour", unitPrice=1500_00, # amount in øre (1500 NOK) incomeAccount="3000", vatType="HIGH", active=True, )) print(f"Product ID: {product.productId}") # List active products for p in co.get_products(active=True): print(p.productId, p.name, p.unitPrice) # Update product.unitPrice = 1600_00 co.update_product(product.productId, product) # Delete co.delete_product(product.productId) ``` -------------------------------- ### FikenPy Async Client: Iterate Through Companies Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Demonstrates asynchronous iteration over companies using the AsyncFikenClient. Requires an active client context. ```python # Iterate through companies async for company in await client.get_companies(): print(company.name) ``` -------------------------------- ### Initialize FikenPy Sync Client with OAuth2 Credentials Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Initialize the synchronous FikenClient using OAuth2 credentials. This is suitable for third-party applications. ```python from fikenpy import FikenClient # Using OAuth2 client = FikenClient( access_token="your_access_token", refresh_token="your_refresh_token", client_id="your_client_id", client_secret="your_client_secret" ) ``` -------------------------------- ### Scoped Client Source: https://context7.com/gronnmann/fikenpy/llms.txt Explains how to create a company-scoped client using `FikenClient.for_company()` or `AsyncFikenClient.for_company()`. This simplifies operations by pre-filling the company slug. ```APIDOC ## Scoped Client `FikenClient.for_company(company_slug)` / `AsyncFikenClient.for_company(company_slug)` — create a company-scoped wrapper that pre-fills `company_slug` on every call. Using a scoped client is the recommended approach when all operations target a single company. The returned `ScopedFikenClient` (or `AsyncScopedFikenClient`) exposes the same methods as the parent client, minus the `company_slug` positional argument. ```python from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # No need to pass company_slug any more for contact in co.get_contacts(): print(contact.name) for invoice in co.get_invoices(): print(invoice.invoiceNumber, invoice.net) for product in co.get_products(): print(product.name, product.unitPrice) ``` ``` -------------------------------- ### Manage Projects Source: https://context7.com/gronnmann/fikenpy/llms.txt Use this code to create, update, and delete projects for tracking income and expenses. Ensure project numbers are unique. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import ProjectRequest, UpdateProjectRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") project = co.create_project(ProjectRequest( name="Website Redesign 2024", number="PROJ-001", startDate=date(2024, 1, 15), endDate=date(2024, 6, 30), contactId=42, )) print(f"Project ID: {project.projectId}") # Update description co.update_project(project.projectId, UpdateProjectRequest( name="Website Redesign 2024 – Extended", completed=False, )) # Delete co.delete_project(project.projectId) ``` -------------------------------- ### FikenPy Scoped Client (Sync) Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Create a scoped synchronous client for a specific company. This avoids repeatedly passing the company slug. ```python # Sync client = FikenClient(api_token="your_api_token") company_client = client.for_company("my-company") # Now you don't need to pass company_slug to every method contacts = company_client.get_contacts() invoices = company_client.get_invoices() products = company_client.get_products() ``` -------------------------------- ### Projects Source: https://context7.com/gronnmann/fikenpy/llms.txt Manage projects for tracking income and expenses using `get_projects`, `create_project`, `get_project`, `update_project`, and `delete_project`. ```APIDOC ## Projects `get_projects()` / `create_project()` / `get_project()` / `update_project()` / `delete_project()` — manage projects for tracking income and expenses. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import ProjectRequest, UpdateProjectRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") project = co.create_project(ProjectRequest( name="Website Redesign 2024", number="PROJ-001", startDate=date(2024, 1, 15), endDate=date(2024, 6, 30), contactId=42, )) print(f"Project ID: {project.projectId}") # Update description co.update_project(project.projectId, UpdateProjectRequest( name="Website Redesign 2024 – Extended", completed=False, )) # Delete co.delete_project(project.projectId) ``` ``` -------------------------------- ### Error Handling Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Demonstrates how to handle FikenPy and httpx exceptions. ```APIDOC ## Error Handling ### Description FikenPy exceptions extend `httpx.HTTPStatusError`, allowing you to catch them using either FikenPy specific exceptions or general httpx exceptions. ### Example ```python from fikenpy import FikenClient, FikenAPIError, FikenNotFoundError import httpx client = FikenClient(api_token="your_token") # Catch specific FikenPy exceptions try: contact = client.get_contact("my-company", 12345) except FikenNotFoundError: print("Contact not found") # Or catch httpx.HTTPStatusError to handle all HTTP errors try: contact = client.get_contact("my-company", 12345) except httpx.HTTPStatusError as e: print(f"HTTP error: {e.response.status_code}") # Or catch the base FikenAPIError try: contact = client.get_contact("my-company", 12345) except FikenAPIError as e: print(f"API error: {e.message}") print(f"Status code: {e.status_code}") print(f"Response data: {e.response_data}") ``` ### Available Exception Classes - `FikenAPIError` - Base exception (extends `httpx.HTTPStatusError`) - `FikenAuthError` - Authentication errors (401, 403) - `FikenNotFoundError` - Resource not found (404) - `FikenValidationError` - Request validation failed (400) - `FikenRateLimitError` - Rate limit exceeded (429) - `FikenMethodNotAllowedError` - HTTP method not allowed (405) - `FikenUnsupportedMediaTypeError` - Media type not supported (415) - `FikenServerError` - Server errors (5xx) ``` -------------------------------- ### Create and Manage Invoice Drafts Source: https://context7.com/gronnmann/fikenpy/llms.txt This snippet shows the workflow for creating, updating, and promoting invoice drafts to final invoices. Drafts allow for iterative editing before finalization. Use `create_invoice_from_draft()` to promote. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import InvoiceishDraftRequest, InvoiceishDraftLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") draft = co.create_invoice_draft(InvoiceishDraftRequest( issueDate=date(2024, 7, 1), daysUntilDueDate=30, customerId=42, lines=[InvoiceishDraftLine( description="July consulting", unitPrice=1500_00, quantity=8, vatType="HIGH", incomeAccount="3000", )], )) print(f"Draft ID: {draft.draftId}") # Promote to a final invoice invoice = co.create_invoice_from_draft(draft.draftId) print(f"Invoice #{invoice.invoiceNumber}") # Or delete the draft # co.delete_invoice_draft(draft.draftId) ``` -------------------------------- ### FikenPy Sync Client: Work with a Specific Company Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Shows how to interact with a specific company by retrieving contacts. Requires a company slug. ```python # Work with a specific company contacts = client.get_contacts(company_slug="my-company") for contact in contacts: print(contact.name) ``` -------------------------------- ### Create Full and Partial Credit Notes Source: https://context7.com/gronnmann/fikenpy/llms.txt Issues credit notes against existing invoices. Supports full reversal or partial crediting of specific lines. ```python from fikenpy import FikenClient from fikenpy.models import FullCreditNoteRequest, PartialCreditNoteRequest, CreditNoteLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Full credit note — reverses the entire invoice cn = co.create_full_credit_note(FullCreditNoteRequest( issueDate="2024-07-01", invoiceId=1001, creditNoteText="Full refund", )) print(f"Credit note ID: {cn.creditNoteId}") # Partial credit note — credit specific lines pcn = co.create_partial_credit_note(PartialCreditNoteRequest( issueDate="2024-07-02", invoiceId=1002, lines=[CreditNoteLine(lineId=3, quantity=2)], )) print(f"Partial credit note ID: {pcn.creditNoteId}") ``` -------------------------------- ### FikenPy Scoped Client (Async) Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Create a scoped asynchronous client for a specific company. This simplifies calls by pre-setting the company slug. ```python # Async async with AsyncFikenClient(api_token="your_api_token") as client: company_client = client.for_company("my-company") contacts = await company_client.get_contacts() async for contact in contacts: print(contact.name) ``` -------------------------------- ### Run Tests and Code Quality Checks Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Execute tests using pytest, perform static type checking with mypy, and run code linting with ruff check. These commands ensure code quality and correctness. ```bash # Run tests pytest # Run type checking mypy src/fikenpy # Run linting ruff check src/fikenpy ``` -------------------------------- ### Send Invoice via Email or EHF Source: https://context7.com/gronnmann/fikenpy/llms.txt This snippet demonstrates how to send an existing invoice to a customer. Specify the invoice ID and the desired sending method (e.g., 'email'). ```python from fikenpy import FikenClient from fikenpy.models import SendInvoiceRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") co.send_invoice(SendInvoiceRequest( invoiceId=1001, method="email", includeDocumentAttachments=True, )) ``` -------------------------------- ### Create and Manage Invoices Source: https://context7.com/gronnmann/fikenpy/llms.txt Use this snippet to create, list, and update customer invoices. Ensure all required fields for InvoiceRequest are provided. The API returns a detailed InvoiceResult upon creation. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import InvoiceRequest, InvoiceLine, UpdateInvoiceRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Create an invoice invoice = co.create_invoice(InvoiceRequest( issueDate=date(2024, 6, 1), dueDate=date(2024, 6, 30), customerId=42, lines=[ InvoiceLine( description="Consulting – June 2024", unitPrice=1500_00, quantity=10, vatType="HIGH", incomeAccount="3000", ) ], )) print(f"Invoice #{invoice.invoiceNumber} created (net={invoice.net})") # List unsettled invoices for inv in co.get_invoices(settled=False): print(inv.invoiceId, inv.invoiceNumber, inv.dueDate) # Mark as sent / update co.update_invoice(invoice.invoiceId, UpdateInvoiceRequest(sent=True)) ``` -------------------------------- ### Create, Read, Update, Delete Contacts in Python Source: https://context7.com/gronnmann/fikenpy/llms.txt Demonstrates full CRUD operations for contacts. Use `get_contacts()` with filters like `customer=True` or `name='Acme'` to retrieve specific contacts. The `Contact` model includes fields like name, email, and customer/supplier status. ```python from fikenpy import FikenClient from fikenpy.models import Contact, Address with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Create a new customer contact new_contact = co.create_contact(Contact( name="Acme AS", email="billing@acme.no", customer=True, supplier=False, phoneNumber="+4712345678", )) print(f"Created contact ID: {new_contact.contactId}") # Fetch all customer contacts for contact in co.get_contacts(customer=True): print(contact.contactId, contact.name) # Update a contact new_contact.email = "newbilling@acme.no" updated = co.update_contact(new_contact.contactId, new_contact) # Delete a contact co.delete_contact(updated.contactId) ``` -------------------------------- ### FikenPy Error Handling with httpx.HTTPStatusError Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Shows how to catch general HTTP errors using httpx.HTTPStatusError, which FikenPy exceptions extend. ```python from fikenpy import FikenClient import httpx client = FikenClient(api_token="your_token") # Or catch httpx.HTTPStatusError to handle all HTTP errors try: contact = client.get_contact("my-company", 12345) except httpx.HTTPStatusError as e: print(f"HTTP error: {e.response.status_code}") ``` -------------------------------- ### Create and Retrieve Journal Entries Source: https://context7.com/gronnmann/fikenpy/llms.txt Use this snippet to create general journal entries with multiple lines and retrieve existing journal entries. Ensure you have the correct account codes and amounts. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import GeneralJournalEntryRequest, JournalEntryLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") entry = co.create_general_journal_entry(GeneralJournalEntryRequest( description="Accrual adjustment June 2024", date=date(2024, 6, 30), lines=[ JournalEntryLine(account="1700", amount=5000_00, debitCredit="DEBIT"), JournalEntryLine(account="3800", amount=5000_00, debitCredit="CREDIT"), ], )) print(f"Journal entry ID: {entry.journalEntryId}") for je in co.get_journal_entries(): print(je.journalEntryId, je.date, je.description) ``` -------------------------------- ### Retrieve and Manage Transactions Source: https://context7.com/gronnmann/fikenpy/llms.txt This snippet demonstrates how to fetch a list of all transactions and retrieve a single transaction by its ID. It also shows how to delete transactions. ```python from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") for tx in co.get_transactions(): print(tx.transactionId, tx.description, tx.lastModifiedDate) # Fetch a single transaction tx = co.get_transaction(5001) print(tx.entries) ``` -------------------------------- ### Manage Contact Persons in Python Source: https://context7.com/gronnmann/fikenpy/llms.txt Handles contact persons, which are sub-resources of a contact. Use `add_contact_person()` to create new persons and `get_contact_persons()` to list them. The `ContactPerson` model includes name, email, and phone number. ```python from fikenpy import FikenClient from fikenpy.models import ContactPerson with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Add a contact person to contact ID 42 person = co.add_contact_person(42, ContactPerson( name="Jane Doe", email="jane@acme.no", phoneNumber="+4798765432", )) print(f"Person ID: {person.contactPersonId}") # List all persons for a contact persons = co.get_contact_persons(42) for p in persons: print(p.contactPersonId, p.name) # Delete co.delete_contact_person(42, person.contactPersonId) ``` -------------------------------- ### FikenPy Error Handling with Specific Exceptions Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Demonstrates catching specific FikenPy exceptions like FikenNotFoundError. Ensure necessary imports are included. ```python from fikenpy import FikenClient, FikenAPIError, FikenNotFoundError import httpx client = FikenClient(api_token="your_token") # Catch specific FikenPy exceptions try: contact = client.get_contact("my-company", 12345) except FikenNotFoundError: print("Contact not found") ``` -------------------------------- ### Accounts Source: https://context7.com/gronnmann/fikenpy/llms.txt Access the chart of accounts and balances using `get_accounts`, `get_account`, `get_account_balances`, and `get_account_balance`. ```APIDOC ## Accounts `get_accounts()` / `get_account()` / `get_account_balances()` / `get_account_balance()` — access the chart of accounts and balances. ```python from datetime import date from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # All accounts in range 1000–3999 for account in co.get_accounts(from_account="1000", to_account="3999"): print(account.code, account.name) # Balance for a specific account on a specific date balance = co.get_account_balance("1920", date=date(2024, 6, 30)) print(f"Balance: {balance.balance} {balance.currency}") # All balances on a given date for ab in co.get_account_balances(date=date(2024, 12, 31)): print(ab.code, ab.balance) ``` ``` -------------------------------- ### Access Chart of Accounts and Balances Source: https://context7.com/gronnmann/fikenpy/llms.txt Retrieve account information and balances. You can filter accounts by range and specify a date for balance retrieval. ```python from datetime import date from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # All accounts in range 1000–3999 for account in co.get_accounts(from_account="1000", to_account="3999"): print(account.code, account.name) # Balance for a specific account on a specific date balance = co.get_account_balance("1920", date=date(2024, 6, 30)) print(f"Balance: {balance.balance} {balance.currency}") # All balances on a given date for ab in co.get_account_balances(date=date(2024, 12, 31)): print(ab.code, ab.balance) ``` -------------------------------- ### Bank Accounts Source: https://context7.com/gronnmann/fikenpy/llms.txt Manage registered bank accounts and read balances using `get_bank_accounts`, `create_bank_account`, `get_bank_account`, and `get_bank_balances`. ```APIDOC ## Bank Accounts `get_bank_accounts()` / `create_bank_account()` / `get_bank_account()` / `get_bank_balances()` — manage registered bank accounts and read balances. ```python from fikenpy import FikenClient from fikenpy.models import BankAccountRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Register a new bank account bank_acc = co.create_bank_account(BankAccountRequest( name="Main operating account", bankAccountNumber="12345678901", bic="DNBANOKKXXX", iban="NO9386011117947", foreignService=False, )) print(f"Bank account ID: {bank_acc.bankAccountId}") # List all active bank accounts for ba in co.get_bank_accounts(inactive=False): print(ba.bankAccountId, ba.name, ba.bankAccountNumber) # Bank balances for bb in co.get_bank_balances(): print(bb.bankAccountId, bb.balance) ``` ``` -------------------------------- ### Credit Notes Source: https://context7.com/gronnmann/fikenpy/llms.txt Issue full or partial credit notes against invoices using `create_full_credit_note` and `create_partial_credit_note`. ```APIDOC ## Credit Notes `get_credit_notes()` / `create_full_credit_note()` / `create_partial_credit_note()` / `get_credit_note()` / `send_credit_note()` — issue full or partial credit notes against invoices. ```python from fikenpy import FikenClient from fikenpy.models import FullCreditNoteRequest, PartialCreditNoteRequest, CreditNoteLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Full credit note — reverses the entire invoice cn = co.create_full_credit_note(FullCreditNoteRequest( issueDate="2024-07-01", invoiceId=1001, creditNoteText="Full refund", )) print(f"Credit note ID: {cn.creditNoteId}") # Partial credit note — credit specific lines pcn = co.create_partial_credit_note(PartialCreditNoteRequest( issueDate="2024-07-02", invoiceId=1002, lines=[CreditNoteLine(lineId=3, quantity=2)], )) print(f"Partial credit note ID: {pcn.creditNoteId}") ``` ``` -------------------------------- ### Error Handling with FikenPy Exceptions Source: https://context7.com/gronnmann/fikenpy/llms.txt Illustrates how to catch specific FikenPy exceptions like FikenNotFoundError, FikenAuthError, FikenValidationError, and FikenAPIError. It also shows how to catch generic httpx.HTTPStatusError. ```python import httpx from fikenpy import FikenClient, FikenAPIError, FikenNotFoundError, FikenAuthError from fikenpy.exceptions import FikenValidationError, FikenServerError with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Catch a specific error try: contact = co.get_contact(999999) except FikenNotFoundError: print("Contact 999999 does not exist") # Catch auth errors try: user = client.get_user() except FikenAuthError as e: print(f"Auth failed [{e.status_code}]: {e.message}") # Catch validation errors with response detail try: co.create_contact(None) # type: ignore except FikenValidationError as e: print(f"Bad request: {e.message}") print(f"Response data: {e.response_data}") # Catch any Fiken error try: co.get_invoice(0) except FikenAPIError as e: print(f"API error {e.status_code}: {e.message}") # Or use httpx directly try: co.get_invoice(0) except httpx.HTTPStatusError as e: print(f"HTTP {e.response.status_code}") ``` -------------------------------- ### Upload and List Inbox Documents Source: https://context7.com/gronnmann/fikenpy/llms.txt Upload documents to the Fiken inbox for later processing and list existing inbox documents. Ensure the file path is correct. ```python from pathlib import Path from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Upload a PDF to the inbox doc = co.create_inbox_document(Path("/tmp/supplier-invoice.pdf")) print(f"Inbox document ID: {doc.documentId}") # List unprocessed inbox documents for item in co.get_inbox(): print(item.documentId, item.name, item.status) ``` -------------------------------- ### Generate Product Sales Report in Python Source: https://context7.com/gronnmann/fikenpy/llms.txt Generates an aggregated sales report for products within a specified date range using `create_product_sales_report()`. The `ProductSalesReportRequest` model is used to define the date range. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import ProductSalesReportRequest with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") report = co.create_product_sales_report(ProductSalesReportRequest( from_=date(2024, 1, 1), to=date(2024, 12, 31), )) for line in report.salesReportLines or []: print(line.productName, line.soldUnits, line.sumNet) ``` -------------------------------- ### Sale Drafts Source: https://context7.com/gronnmann/fikenpy/llms.txt Manage sale drafts with `create_sale_draft`, `update_sale_draft`, `delete_sale_draft`, and create sales from drafts using `create_sale_from_draft`. ```APIDOC ## Sale Drafts `get_sale_drafts()` / `create_sale_draft()` / `update_sale_draft()` / `delete_sale_draft()` / `create_sale_from_draft()` — draft-based sale workflow, mirroring invoice drafts. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import DraftRequest, DraftLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") draft = co.create_sale_draft(DraftRequest( date=date(2024, 7, 5), type="CASH_SALE", currency="NOK", lines=[DraftLine( description="Workshop fee", unitPrice=500_00, quantity=2, vatType="HIGH", account="3000", )], )) sale = co.create_sale_from_draft(draft.draftId) print(f"Sale ID: {sale.saleId}") ``` ``` -------------------------------- ### Create Contact Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Create a new contact within a specific company. ```APIDOC ## Create Contact ### Description Create a new contact within a specific company. ### Parameters #### Path Parameters - **company_slug** (string) - Required - The unique identifier for the company. #### Request Body - **data** (ContactRequest) - Required - The data for the new contact. - **name** (string) - Required - The name of the contact. - **email** (string) - Optional - The email address of the contact. - **customer** (boolean) - Optional - Whether the contact is a customer. ### Method (Sync) ```python client.create_contact( company_slug="my-company", data=ContactRequest( name="John Doe", email="john@example.com", customer=True ) ) ``` ``` -------------------------------- ### Manage Invoice Attachments Source: https://context7.com/gronnmann/fikenpy/llms.txt Use this code to upload files as attachments to an invoice or to list existing attachments. Ensure the file path is correct when uploading. ```python from pathlib import Path from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Upload a PDF receipt to invoice 1001 co.add_attachment_to_invoice(1001, Path("/tmp/receipt.pdf")) # List existing attachments for att in co.get_invoice_attachments(1001): print(att.filename, att.downloadUrl) ``` -------------------------------- ### Create Sale Payment Source: https://context7.com/gronnmann/fikenpy/llms.txt Records a payment against a specific sale. Ensure the sale ID and payment details are correct. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import Payment with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") payment = co.create_sale_payment(101, Payment( date=date(2024, 6, 20), account="1920:10001", amount=897_00, currency="NOK", )) print(f"Payment ID: {payment.paymentId}") ``` -------------------------------- ### Scoped Client Source: https://github.com/gronnmann/fikenpy/blob/master/README.md Create a scoped client for a specific company to avoid repeatedly passing the company slug. ```APIDOC ## Scoped Client ### Description Create a scoped client for a specific company to avoid repeatedly passing the company slug. ### Method (Sync) ```python client = FikenClient(api_token="your_api_token") company_client = client.for_company("my-company") # Now you don't need to pass company_slug to every method contacts = company_client.get_contacts() ``` ### Method (Async) ```python async with AsyncFikenClient(api_token="your_api_token") as client: company_client = client.for_company("my-company") contacts = await company_client.get_contacts() async for contact in contacts: print(contact.name) ``` ``` -------------------------------- ### Add Attachment to Purchase Source: https://context7.com/gronnmann/fikenpy/llms.txt Attaches a file, such as a receipt, to a purchase record. Can optionally be linked to a payment or sale. ```python from pathlib import Path from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Attach a receipt PDF; mark it as documenting the purchase (not payment) co.add_attachment_to_purchase( 201, Path("/tmp/invoice-supplier.pdf"), attach_to_payment=False, attach_to_sale=True, ) ``` -------------------------------- ### Products Management Source: https://context7.com/gronnmann/fikenpy/llms.txt Provides CRUD operations for managing the product and service catalogue. Includes creating, retrieving, updating, and deleting products. ```APIDOC ## Products `get_products()` / `create_product()` / `get_product()` / `update_product()` / `delete_product()` — manage product / service catalogue. The `Product` model includes `name`, `unitPrice`, `incomeAccount`, `vatType`, `active`, and `productNumber`. ```python from fikenpy import FikenClient from fikenpy.models import Product with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Create a product product = co.create_product(Product( name="Consulting Hour", unitPrice=1500_00, # amount in øre (1500 NOK) incomeAccount="3000", vatType="HIGH", active=True, )) print(f"Product ID: {product.productId}") # List active products for p in co.get_products(active=True): print(p.productId, p.name, p.unitPrice) # Update product.unitPrice = 1600_00 co.update_product(product.productId, product) # Delete co.delete_product(product.productId) ``` ``` -------------------------------- ### Create Purchase Record Source: https://context7.com/gronnmann/fikenpy/llms.txt Records a supplier invoice or expense. Requires supplier ID and line item details. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import PurchaseRequest, PurchaseLine with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") purchase = co.create_purchase(PurchaseRequest( date=date(2024, 6, 10), kind="SUPPLIER_INVOICE", supplierId=77, currency="NOK", lines=[PurchaseLine( description="Office supplies", netAmount=800_00, vatAmount=200_00, vatType="HIGH", account="6800", )], dueDate=date(2024, 7, 10), paymentAccount="2400:10001", )) print(f"Purchase ID: {purchase.purchaseId}") ``` -------------------------------- ### Create Purchase Payment Source: https://context7.com/gronnmann/fikenpy/llms.txt Records a payment made for a specific purchase. Requires the purchase ID and payment details. ```python from datetime import date from fikenpy import FikenClient from fikenpy.models import Payment with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") payment = co.create_purchase_payment(201, Payment( date=date(2024, 7, 10), account="1920:10001", amount=1000_00, currency="NOK", )) print(f"Payment ID: {payment.paymentId}") ``` -------------------------------- ### Purchase Attachments Source: https://context7.com/gronnmann/fikenpy/llms.txt Attach a receipt or document to a purchase using `add_attachment_to_purchase`. ```APIDOC ## Purchase Attachments `add_attachment_to_purchase(purchase_id, file, filename=None, attach_to_payment=False, attach_to_sale=True)` — attach a receipt or document to a purchase. ```python from pathlib import Path from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: co = client.for_company("my-company-as") # Attach a receipt PDF; mark it as documenting the purchase (not payment) co.add_attachment_to_purchase( 201, Path("/tmp/invoice-supplier.pdf"), attach_to_payment=False, attach_to_sale=True, ) ``` ``` -------------------------------- ### Retrieve Authenticated User Information Source: https://context7.com/gronnmann/fikenpy/llms.txt Fetches information about the currently authenticated user using the `get_user()` method. The returned `Userinfo` model contains details like name and email. ```python from fikenpy import FikenClient with FikenClient(api_token="YOUR_API_TOKEN") as client: user = client.get_user() # Userinfo fields: name, email, ... print(f"Logged in as: {user.name} ({user.email})") ```