Summary
Several models are missing fields that the Moneybird API returns, so those values are silently dropped (the base model is configured with extra="ignore"). This was found by diffing each model against the official OpenAPI response schemas. Below is a per-entity checklist of the missing response fields, with the type each field has in the spec so implementation is mechanical.
Type conventions used below (taken from the spec's shared definitions):
- timestamp =
string, date-time → suggest str | None
- identifier =
string|integer matching ^\d+$ → suggest matching the codebase's identifier convention (see the separate "standardize identifier typing" issue); shown as int | str | None below
- Amount/total fields are strings in the API (e.g.
"119.79"), not numbers.
Nested collections (events, notes, attachments, time_entries) are lower priority and can be added as loosely-typed list[dict[str, Any]] or skipped; the scalar fields are the higher-value gaps.
ExternalSalesInvoice (largest gap)
moneysnake/external_sales_invoice.py is missing the entire read-back surface:
(version is covered by a separate issue.)
Contact
moneysnake/contact.py is missing:
(version is covered by a separate issue.) Note: type and from_checkout on the model are request-only params, not part of the response schema — worth a comment but not a bug.
Payment
moneysnake/payment.py is missing:
SalesInvoice
moneysnake/sales_invoice.py is missing scalars:
(Nested contact, contact_person, attachments, events, notes, time_entries optional.)
Document (PurchaseInvoice / Receipt)
moneysnake/document.py is missing:
FinancialMutation
moneysnake/financial_mutation.py is missing:
Detail line items
The *DetailsAttribute classes drop read-back fields returned by the API (fine to omit from write payloads, but they disappear on read):
Verification
- The repo's
tests/conftest.py fixtures already carry full spec-shaped responses (e.g. contact_data includes email, archived, version, sales_invoices_url) — extend the model tests to assert these fields survive a round-trip instead of being dropped.
Note
Many of these are shared across entities (administration_id, created_at, updated_at, version). It may be cleaner to introduce a small shared base for those common read-only fields rather than re-adding them per model — this pairs well with the mixin/base extraction tracked in the related refactor issues.
Summary
Several models are missing fields that the Moneybird API returns, so those values are silently dropped (the base model is configured with
extra="ignore"). This was found by diffing each model against the official OpenAPI response schemas. Below is a per-entity checklist of the missing response fields, with the type each field has in the spec so implementation is mechanical.Type conventions used below (taken from the spec's shared definitions):
string, date-time→ suggeststr | Nonestring|integermatching^\d+$→ suggest matching the codebase's identifier convention (see the separate "standardize identifier typing" issue); shown asint | str | Nonebelow"119.79"), not numbers.Nested collections (
events,notes,attachments,time_entries) are lower priority and can be added as loosely-typedlist[dict[str, Any]]or skipped; the scalar fields are the higher-value gaps.ExternalSalesInvoice(largest gap)moneysnake/external_sales_invoice.pyis missing the entire read-back surface:state: str | None(spec: string)created_at: str | None,updated_at: str | None(timestamps)paid_at: str | None(spec: string|null)entry_number: int | None(spec: integer)origin: str | None(spec: string|null)marked_dubious_on: str | None,marked_uncollectible_on: str | None(spec: string|null)tax_totals: list[dict[str, Any]](spec: array of tax_subtotal objects;SalesInvoicealready types this field the same way)total_paid: str | None,total_unpaid: str | None,total_unpaid_base: str | None(spec: string)total_price_excl_tax: str | None,total_price_excl_tax_base: str | None(spec: string)total_price_incl_tax: str | None,total_price_incl_tax_base: str | None(spec: string)(
versionis covered by a separate issue.)Contactmoneysnake/contact.pyis missing:email: str | None(spec: string|null)created_at: str | None,updated_at: str | None(timestamps)archived: bool | None(spec: boolean)tax_number_valid: bool | None(spec: boolean|null)tax_number_validated_at: str | None(spec: string|null)sales_invoices_url: str | None(spec: string)(
versionis covered by a separate issue.) Note:typeandfrom_checkouton the model are request-only params, not part of the response schema — worth a comment but not a bug.Paymentmoneysnake/payment.pyis missing:created_at: str | None,updated_at: str | None(timestamps)user_id: int | str | None(identifier)invoice_type: str | None(spec: string, e.g."SalesInvoice")credit_invoice_id: int | str | None(identifier, nullable)linked_payment_id: int | str | None(identifier, nullable)payment_transaction_id: int | str | None(identifier, nullable)SalesInvoicemoneysnake/sales_invoice.pyis missing scalars:original_sales_invoice_id: int | str | None(identifier, nullable)public_view_code_expires_at: str | None(spec: string|null)(Nested
contact,contact_person,attachments,events,notes,time_entriesoptional.)Document(PurchaseInvoice / Receipt)moneysnake/document.pyis missing:fiscal_allocations: list[dict[str, Any]](spec: array of fiscal_allocation objects)administration_id: int | str | None(identifier)attachments,events,notesaslist[dict[str, Any]]FinancialMutationmoneysnake/financial_mutation.pyis missing:settlement_state: str | None(spec: string)Detail line items
The
*DetailsAttributeclasses drop read-back fields returned by the API (fine to omit from write payloads, but they disappear on read):amount_decimal: str | None(spec: string|null)total_price_excl_tax_with_discount: str | None,total_price_excl_tax_with_discount_base: str | None(spec: number serialized as string, e.g."99.0")created_at: str | None,updated_at: str | None(spec: string|null)tax_report_reference: list[str] | None(spec: array of string|null)mandatory_tax_text: str | None(spec: string|null)Verification
tests/conftest.pyfixtures already carry full spec-shaped responses (e.g.contact_dataincludesemail,archived,version,sales_invoices_url) — extend the model tests to assert these fields survive a round-trip instead of being dropped.Note
Many of these are shared across entities (
administration_id,created_at,updated_at,version). It may be cleaner to introduce a small shared base for those common read-only fields rather than re-adding them per model — this pairs well with the mixin/base extraction tracked in the related refactor issues.