Skip to content

transactions#

Lunch Money - Transactions

https://lunchmoney.dev/#transactions

FullStatusEnum #

Bases: str, Enum

Status Options

Source code in lunchable/models/transactions.py
class FullStatusEnum(str, Enum):
    """
    Status Options
    """

    cleared = "cleared"
    uncleared = "uncleared"
    recurring = "recurring"
    recurring_suggested = "recurring_suggested"
    pending = "pending"

TransactionBaseObject #

Bases: LunchableModel

Base Model For All Transactions to Inherit From

Source code in lunchable/models/transactions.py
class TransactionBaseObject(LunchableModel):
    """
    Base Model For All Transactions to Inherit From
    """

    pass

TransactionChildObject #

Bases: TransactionBaseObject

Child Transaction Object for Transaction Groups

Parameters:

Name Type Description Default
id int

Unique identifier for transaction

required
amount float

Amount of the transaction in numeric format to 4 decimal places

required
payee str | None

Name of payee. If recurring_id is not null, this field will show the payee of associated recurring expense instead of the original transaction payee

None
date date

Date of transaction in ISO 8601 format

required
formatted_date str | None

Date of transaction in user's preferred format

None
notes str | None

User-entered transaction notes If recurring_id is not null, this field will be description of associated recurring expense

None
currency str | None

Three-letter lowercase currency code of the transaction in ISO 4217 format

None
asset_id int | None

Unique identifier of associated manually-managed account (see Assets) Note: plaid_account_id and asset_id cannot both exist for a transaction

None
plaid_account_id int | None

Unique identifier of associated Plaid account (see Plaid Accounts) Note: plaid_account_id and asset_id cannot both exist for a transaction

None
to_base float | None

The amount converted to the user's primary currency. If the multicurrency feature is not being used, to_base and amount will be the same.

None
Source code in lunchable/models/transactions.py
class TransactionChildObject(TransactionBaseObject):
    """
    Child Transaction Object for Transaction Groups
    """

    id: int = Field(description=_TransactionDescriptions.id)
    amount: float = Field(description=_TransactionDescriptions.amount)
    payee: Optional[str] = Field(None, description=_TransactionDescriptions.payee)
    date: datetime.date = Field(description=_TransactionDescriptions.date)
    formatted_date: Optional[str] = Field(
        None, description=_TransactionDescriptions.formatted_date
    )
    notes: Optional[str] = Field(None, description=_TransactionDescriptions.notes)
    currency: Optional[str] = Field(None, description=_TransactionDescriptions.currency)
    asset_id: Optional[int] = Field(None, description=_TransactionDescriptions.asset_id)
    plaid_account_id: Optional[int] = Field(
        None, description=_TransactionDescriptions.plaid_account_id
    )
    to_base: Optional[float] = Field(None, description=_TransactionDescriptions.to_base)

TransactionInsertObject #

Bases: TransactionBaseObject

Object For Creating New Transactions

https://lunchmoney.dev/#insert-transactions

Parameters:

Name Type Description Default
date date

Must be in ISO 8601 format (YYYY-MM-DD).

required
amount float

Numeric value of amount. i.e. $4.25 should be denoted as 4.25.

required
category_id int | None

Unique identifier for associated category_id. Category must be associated with the same account and must not be a category group.

None
payee str | None

Max 140 characters

None
currency str | None

Three-letter lowercase currency code in ISO 4217 format. The code sent must exist in our database. Defaults to user account's primary currency.

None
asset_id int | None

Unique identifier for associated asset (manually-managed account). Asset must be associated with the same account.

None
recurring_id int | None

Unique identifier for associated recurring expense. Recurring expense must be associated with the same account.

None
notes str | None

Max 350 characters

None
status StatusEnum | None

Must be either cleared or uncleared. If recurring_id is provided, the status will automatically be set to recurring or recurring_suggested depending on the type of recurring_id. Defaults to uncleared.

None
external_id str | None

User-defined external ID for transaction. Max 75 characters. External IDs must be unique within the same asset_id.

None
tags List[Union[str, int]] | None

Passing in a number will attempt to match by ID. If no matching tag ID is found, an error will be thrown. Passing in a string will attempt to match by string. If no matching tag name is found, a new tag will be created.

None
Source code in lunchable/models/transactions.py
class TransactionInsertObject(TransactionBaseObject):
    """
    Object For Creating New Transactions

    https://lunchmoney.dev/#insert-transactions
    """

    class StatusEnum(str, Enum):
        """
        Status Options, must be "cleared" or "uncleared"
        """

        cleared = "cleared"
        uncleared = "uncleared"

    date: datetime.date = Field(description=_TransactionInsertDescriptions.date)
    amount: float = Field(description=_TransactionInsertDescriptions.amount)
    category_id: Optional[int] = Field(
        None, description=_TransactionInsertDescriptions.category_id
    )
    payee: Optional[str] = Field(None, description="Max 140 characters", max_length=140)
    currency: Optional[str] = Field(
        None, description=_TransactionInsertDescriptions.currency, max_length=3
    )
    asset_id: Optional[int] = Field(
        None, description=_TransactionInsertDescriptions.asset_id
    )
    recurring_id: Optional[int] = Field(
        None, description=_TransactionInsertDescriptions.recurring_id
    )
    notes: Optional[str] = Field(None, description="Max 350 characters", max_length=350)
    status: Optional[StatusEnum] = Field(
        None, description=_TransactionInsertDescriptions.status
    )
    external_id: Optional[str] = Field(
        None, description=_TransactionInsertDescriptions.external_id, max_length=75
    )
    tags: Optional[List[Union[str, int]]] = Field(
        None, description=_TransactionInsertDescriptions.tags
    )

StatusEnum #

Bases: str, Enum

Status Options, must be "cleared" or "uncleared"

Source code in lunchable/models/transactions.py
class StatusEnum(str, Enum):
    """
    Status Options, must be "cleared" or "uncleared"
    """

    cleared = "cleared"
    uncleared = "uncleared"

TransactionObject #

Bases: TransactionBaseObject

Universal Lunch Money Transaction Object

https://lunchmoney.dev/#transaction-object

Parameters:

Name Type Description Default
id int

Unique identifier for transaction

required
date date

Date of transaction in ISO 8601 format

required
payee str | None

Name of payee. If recurring_id is not null, this field will show the payee of associated recurring expense instead of the original transaction payee

None
amount float

Amount of the transaction in numeric format to 4 decimal places

required
currency str | None

Three-letter lowercase currency code of the transaction in ISO 4217 format

None
to_base float | None

The amount converted to the user's primary currency. If the multicurrency feature is not being used, to_base and amount will be the same.

None
category_id int | None

Unique identifier of associated category

None
category_name str | None

Name of category associated with transaction

None
category_group_id int | None

Unique identifier of associated category group, if any

None
category_group_name str | None

Name of category group associated with transaction, if any

None
is_income bool | None

Based on the associated category's property, denotes if transaction is treated as income

None
exclude_from_budget bool | None

Based on the associated category's property, denotes if transaction is excluded from budget

None
exclude_from_totals bool | None

Based on the associated category's property, denotes if transaction is excluded from totals

None
created_at datetime

The date and time of when the transaction was created (in the ISO 8601 extended format).

required
updated_at datetime

The date and time of when the transaction was last updated (in the ISO 8601 extended format).

required
status str | None

One of the following:

  • cleared: User has reviewed the transaction
  • uncleared: User has not yet reviewed the transaction
  • recurring: Transaction is linked to a recurring expense
  • recurring_suggested: Transaction is listed as a suggested transaction for an existing recurring expense.
  • pending: Imported transaction is marked as pending. This should be a temporary state.
User intervention is required to change this to recurring.

None
is_pending bool | None

Denotes if transaction is pending (not posted)

None
notes str | None

User-entered transaction notes If recurring_id is not null, this field will be description of associated recurring expense

None
original_name str | None

The transactions original name before any payee name updates. For synced transactions, this is the raw original payee name from your bank.

None
recurring_id int | None

Unique identifier of associated recurring item

None
recurring_payee str | None

Payee name of associated recurring item

None
recurring_description str | None

Description of associated recurring item

None
recurring_cadence str | None

Cadence of associated recurring item (one of once a week, every 2 weeks, twice a month, monthly, every 2 months, every 3 months, every 4 months, twice a year, yearly)

None
recurring_type str | None

Type of associated recurring (one of cleared, suggested, dismissed)

None
recurring_amount float | None

Amount of associated recurring item

None
recurring_currency str | None

Currency of associated recurring item

None
parent_id int | None

Exists if this is a split transaction. Denotes the transaction ID of the original transaction. Note that the parent transaction is not returned in this call.

None
has_children bool | None

True if this transaction is a parent transaction and is split into 2 or more other transactions

None
group_id int | None

Exists if this transaction is part of a group. Denotes the parent’s transaction ID

None
is_group bool | None

True if this transaction represents a group of transactions. If so, amount and currency represent the totalled amount of transactions bearing this transaction’s id as their group_id. Amount is calculated based on the user’s primary currency.

None
asset_id int | None

Unique identifier of associated manually-managed account (see Assets) Note: plaid_account_id and asset_id cannot both exist for a transaction

None
asset_institution_name str | None

Institution name of associated manually-managed account

None
asset_name str | None

Name of associated manually-managed account

None
asset_display_name str | None

Display name of associated manually-managed account

None
asset_status str | None

Status of associated manually-managed account (one of active, closed)

None
plaid_account_id int | None

Unique identifier of associated Plaid account (see Plaid Accounts) Note: plaid_account_id and asset_id cannot both exist for a transaction

None
plaid_account_name str | None

Name of associated Plaid account

None
plaid_account_mask str | None

Mask of associated Plaid account

None
institution_name str | None

Institution name of associated Plaid account

None
plaid_account_display_name str | None

Display name of associated Plaid account

None
plaid_metadata Dict[str, Any] | None

Metadata associated with imported transaction from Plaid

None
source str | None

Source of the transaction (one of api, csv, manual,merge,plaid, recurring,rule,user)

None
display_name str | None

Display name for payee for transaction based on whether or not it is linked to a recurring item. If linked, returns recurring_payee field. Otherwise, returns the payee field.

None
display_notes str | None

Display notes for transaction based on whether or not it is linked to a recurring item. If linked, returns recurring_notes field. Otherwise, returns the notes field.

None
account_display_name str | None

Display name for associated account (manual or Plaid). If this is a synced account, returns plaid_account_display_name or asset_display_name.

None
tags List[TagsObject] | None

Array of Tag objects

None
external_id str | None

User-defined external ID for any manually-entered or imported transaction. External ID cannot be accessed or changed for Plaid-imported transactions. External ID must be unique by asset_id. Max 75 characters.

None
children List[TransactionChildObject] | None

Array of Transaction objects. Only exists if this transaction is a parent transaction and is split into 2 or more other transactions. Child transactions do not contain all of the same fields as parent transactions.

None
Source code in lunchable/models/transactions.py
class TransactionObject(TransactionBaseObject):
    """
    Universal Lunch Money Transaction Object

    https://lunchmoney.dev/#transaction-object
    """

    id: int = Field(description=_TransactionDescriptions.id)
    date: datetime.date = Field(description=_TransactionDescriptions.date)
    payee: Optional[str] = Field(None, description=_TransactionDescriptions.payee)
    amount: float = Field(description=_TransactionDescriptions.amount)
    currency: Optional[str] = Field(
        None, max_length=3, description=_TransactionDescriptions.currency
    )
    to_base: Optional[float] = Field(None, description=_TransactionDescriptions.to_base)
    category_id: Optional[int] = Field(
        None, description=_TransactionDescriptions.category_id
    )
    category_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.category_name
    )
    category_group_id: Optional[int] = Field(
        None, description=_TransactionDescriptions.category_group_id
    )
    category_group_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.category_group_name
    )
    is_income: Optional[bool] = Field(
        None, description=_TransactionDescriptions.is_income
    )
    exclude_from_budget: Optional[bool] = Field(
        None, description=_TransactionDescriptions.exclude_from_budget
    )
    exclude_from_totals: Optional[bool] = Field(
        None, description=_TransactionDescriptions.exclude_from_totals
    )
    created_at: datetime.datetime = Field(
        description=_TransactionDescriptions.created_at
    )
    updated_at: datetime.datetime = Field(
        description=_TransactionDescriptions.updated_at
    )
    status: Optional[str] = Field(None, description=_TransactionDescriptions.status)
    is_pending: Optional[bool] = Field(
        None, description=_TransactionDescriptions.is_pending
    )
    notes: Optional[str] = Field(None, description=_TransactionDescriptions.notes)
    original_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.original_name
    )
    recurring_id: Optional[int] = Field(
        None, description=_TransactionDescriptions.recurring_id
    )
    recurring_payee: Optional[str] = Field(
        None, description=_TransactionDescriptions.recurring_payee
    )
    recurring_description: Optional[str] = Field(
        None, description=_TransactionDescriptions.recurring_description
    )
    recurring_cadence: Optional[str] = Field(
        None, description=_TransactionDescriptions.recurring_cadence
    )
    recurring_type: Optional[str] = Field(
        None, description=_TransactionDescriptions.recurring_type
    )
    recurring_amount: Optional[float] = Field(
        None, description=_TransactionDescriptions.recurring_amount
    )
    recurring_currency: Optional[str] = Field(
        None, description=_TransactionDescriptions.recurring_currency
    )
    parent_id: Optional[int] = Field(
        None, description=_TransactionDescriptions.parent_id
    )
    has_children: Optional[bool] = Field(
        None, description=_TransactionDescriptions.has_children
    )
    group_id: Optional[int] = Field(None, description=_TransactionDescriptions.group_id)
    is_group: Optional[bool] = Field(
        None, description=_TransactionDescriptions.is_group
    )
    asset_id: Optional[int] = Field(None, description=_TransactionDescriptions.asset_id)
    asset_institution_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.asset_institution_name
    )
    asset_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.asset_name
    )
    asset_display_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.asset_display_name
    )
    asset_status: Optional[str] = Field(
        None, description=_TransactionDescriptions.asset_status
    )
    plaid_account_id: Optional[int] = Field(
        None, description=_TransactionDescriptions.plaid_account_id
    )
    plaid_account_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.plaid_account_name
    )
    plaid_account_mask: Optional[str] = Field(
        None, description=_TransactionDescriptions.plaid_account_mask
    )
    institution_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.institution_name
    )
    plaid_account_display_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.plaid_account_display_name
    )
    plaid_metadata: Optional[Dict[str, Any]] = Field(
        None, description=_TransactionDescriptions.plaid_metadata
    )
    source: Optional[str] = Field(None, description=_TransactionDescriptions.source)
    display_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.display_name
    )
    display_notes: Optional[str] = Field(
        None, description=_TransactionDescriptions.display_notes
    )
    account_display_name: Optional[str] = Field(
        None, description=_TransactionDescriptions.account_display_name
    )
    tags: Optional[List[TagsObject]] = Field(None, description="Array of Tag objects")
    external_id: Optional[str] = Field(
        None, max_length=75, description=_TransactionDescriptions.external_id
    )
    children: Optional[List[TransactionChildObject]] = Field(
        None, description=_TransactionDescriptions.children
    )

    @field_validator("plaid_metadata", mode="before")
    def to_json(cls, x: Optional[str]) -> Optional[Dict[str, Any]]:
        """
        Check a result
        """
        if x is None:
            return None
        elif isinstance(x, dict):
            return x
        else:
            return pydantic_core.from_json(x)

    def get_update_object(self) -> TransactionUpdateObject:
        """
        Return a TransactionUpdateObject

        Return a TransactionUpdateObject to update an expense. Simply
        change one of the properties and perform an `update_transaction` with
        your Lunchable object.

        Returns
        -------
        TransactionUpdateObject
        """
        update_dict = self.model_dump()
        try:
            TransactionUpdateObject.StatusEnum(self.status)
        except ValueError:
            update_dict["status"] = None
        update_object = TransactionUpdateObject.model_validate(update_dict)
        if update_object.tags is not None:
            tags = [] if self.tags is None else self.tags
            update_object.tags = [tag.name for tag in tags]
        return update_object

    def get_insert_object(self) -> TransactionInsertObject:
        """
        Return a TransactionInsertObject

        Return a TransactionInsertObject to update an expense. Simply
        change some of the properties and perform an `insert_transactions` with
        your Lunchable object.

        Returns
        -------
        TransactionInsertObject
        """
        insert_dict = self.model_dump()
        try:
            TransactionInsertObject.StatusEnum(self.status)
        except ValueError:
            insert_dict["status"] = None
        insert_object = TransactionInsertObject.model_validate(insert_dict)
        if insert_object.tags is not None:
            tags = [] if self.tags is None else self.tags
            insert_object.tags = [tag.name for tag in tags]
        return insert_object

get_insert_object() #

Return a TransactionInsertObject

Return a TransactionInsertObject to update an expense. Simply change some of the properties and perform an insert_transactions with your Lunchable object.

Returns:

Type Description
TransactionInsertObject
Source code in lunchable/models/transactions.py
def get_insert_object(self) -> TransactionInsertObject:
    """
    Return a TransactionInsertObject

    Return a TransactionInsertObject to update an expense. Simply
    change some of the properties and perform an `insert_transactions` with
    your Lunchable object.

    Returns
    -------
    TransactionInsertObject
    """
    insert_dict = self.model_dump()
    try:
        TransactionInsertObject.StatusEnum(self.status)
    except ValueError:
        insert_dict["status"] = None
    insert_object = TransactionInsertObject.model_validate(insert_dict)
    if insert_object.tags is not None:
        tags = [] if self.tags is None else self.tags
        insert_object.tags = [tag.name for tag in tags]
    return insert_object

get_update_object() #

Return a TransactionUpdateObject

Return a TransactionUpdateObject to update an expense. Simply change one of the properties and perform an update_transaction with your Lunchable object.

Returns:

Type Description
TransactionUpdateObject
Source code in lunchable/models/transactions.py
def get_update_object(self) -> TransactionUpdateObject:
    """
    Return a TransactionUpdateObject

    Return a TransactionUpdateObject to update an expense. Simply
    change one of the properties and perform an `update_transaction` with
    your Lunchable object.

    Returns
    -------
    TransactionUpdateObject
    """
    update_dict = self.model_dump()
    try:
        TransactionUpdateObject.StatusEnum(self.status)
    except ValueError:
        update_dict["status"] = None
    update_object = TransactionUpdateObject.model_validate(update_dict)
    if update_object.tags is not None:
        tags = [] if self.tags is None else self.tags
        update_object.tags = [tag.name for tag in tags]
    return update_object

to_json(x) #

Check a result

Source code in lunchable/models/transactions.py
@field_validator("plaid_metadata", mode="before")
def to_json(cls, x: Optional[str]) -> Optional[Dict[str, Any]]:
    """
    Check a result
    """
    if x is None:
        return None
    elif isinstance(x, dict):
        return x
    else:
        return pydantic_core.from_json(x)

TransactionSplitObject #

Bases: TransactionBaseObject

Object for Splitting Transactions

https://lunchmoney.dev/#split-object

Parameters:

Name Type Description Default
date date

Must be in ISO 8601 format (YYYY-MM-DD).

required
category_id int | None

Unique identifier for associated category_id. Category must be associated with the same account.

None
notes str | None

Transaction Split Notes.

None
amount float

Individual amount of split. Currency will inherit from parent transaction. All amounts must sum up to parent transaction amount.

required
Source code in lunchable/models/transactions.py
class TransactionSplitObject(TransactionBaseObject):
    """
    Object for Splitting Transactions

    https://lunchmoney.dev/#split-object
    """

    date: datetime.date = Field(description=_TransactionSplitDescriptions.date)
    category_id: Optional[int] = Field(
        default=None, description=_TransactionSplitDescriptions.category_id
    )
    notes: Optional[str] = Field(None, description=_TransactionSplitDescriptions.notes)
    amount: float = Field(description=_TransactionSplitDescriptions.amount)

TransactionUpdateObject #

Bases: TransactionBaseObject

Object For Updating Existing Transactions

https://lunchmoney.dev/#update-transaction

Parameters:

Name Type Description Default
date date | None

Must be in ISO 8601 format (YYYY-MM-DD).

None
category_id int | None

Unique identifier for associated category_id. Category must be associated with the same account and must not be a category group.

None
payee str | None

Max 140 characters

None
amount float | None

You may only update this if this transaction was not created from an automatic import, i.e. if this transaction is not associated with a plaid_account_id

None
currency str | None

You may only update this if this transaction was not created from an automatic import, i.e. if this transaction is not associated with a plaid_account_id. Defaults to user account's primary currency.

None
asset_id int | None

Unique identifier for associated asset (manually-managed account). Asset must be associated with the same account. You may only update this if this transaction was not created from an automatic import, i.e. if this transaction is not associated with a plaid_account_id

None
recurring_id int | None

Unique identifier for associated recurring expense. Recurring expense must be associated with the same account.

None
notes str | None

Max 350 characters

None
status StatusEnum | None

Must be either cleared or uncleared. Defaults to uncleared If recurring_id is provided, the status will automatically be set to recurring or recurring_suggested depending on the type of recurring_id. Defaults to uncleared.

None
external_id str | None

User-defined external ID for transaction. Max 75 characters. External IDs must be unique within the same asset_id. You may only update this if this transaction was not created from an automatic import, i.e. if this transaction is not associated with a plaid_account_id

None
tags List[Union[str, int]] | None

Passing in a number will attempt to match by ID. If no matching tag ID is found, an error will be thrown. Passing in a string will attempt to match by string. If no matching tag name is found, a new tag will be created.

None
Source code in lunchable/models/transactions.py
class TransactionUpdateObject(TransactionBaseObject):
    """
    Object For Updating Existing Transactions

    https://lunchmoney.dev/#update-transaction
    """

    class StatusEnum(str, Enum):
        """
        Status Options, must be "cleared" or "uncleared"
        """

        cleared = "cleared"
        uncleared = "uncleared"

    date: Optional[datetime.date] = Field(
        None, description=_TransactionUpdateDescriptions.date
    )
    category_id: Optional[int] = Field(
        None, description=_TransactionUpdateDescriptions.category_id
    )
    payee: Optional[str] = Field(None, description="Max 140 characters", max_length=140)
    amount: Optional[float] = Field(
        None, description=_TransactionUpdateDescriptions.amount
    )
    currency: Optional[str] = Field(
        None, description=_TransactionUpdateDescriptions.currency
    )
    asset_id: Optional[int] = Field(
        None, description=_TransactionUpdateDescriptions.asset_id
    )
    recurring_id: Optional[int] = Field(
        None, description=_TransactionUpdateDescriptions.recurring_id
    )
    notes: Optional[str] = Field(None, description="Max 350 characters", max_length=350)
    status: Optional[StatusEnum] = Field(
        None, description=_TransactionUpdateDescriptions.status
    )
    external_id: Optional[str] = Field(
        None, description=_TransactionUpdateDescriptions.external_id
    )
    tags: Optional[List[Union[int, str]]] = Field(
        None, description=_TransactionUpdateDescriptions.tags
    )

StatusEnum #

Bases: str, Enum

Status Options, must be "cleared" or "uncleared"

Source code in lunchable/models/transactions.py
class StatusEnum(str, Enum):
    """
    Status Options, must be "cleared" or "uncleared"
    """

    cleared = "cleared"
    uncleared = "uncleared"

TransactionsClient #

Bases: LunchMoneyAPIClient

Lunch Money Transactions Interactions

Source code in lunchable/models/transactions.py
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
class TransactionsClient(LunchMoneyAPIClient):
    """
    Lunch Money Transactions Interactions
    """

    def get_transactions(
        self,
        start_date: Optional[Union[datetime.date, datetime.datetime, str]] = None,
        end_date: Optional[Union[datetime.date, datetime.datetime, str]] = None,
        tag_id: Optional[int] = None,
        recurring_id: Optional[int] = None,
        plaid_account_id: Optional[int] = None,
        category_id: Optional[int] = None,
        asset_id: Optional[int] = None,
        group_id: Optional[int] = None,
        is_group: Optional[bool] = None,
        status: Optional[str] = None,
        offset: Optional[int] = None,
        limit: Optional[int] = None,
        debit_as_negative: Optional[bool] = None,
        pending: Optional[bool] = None,
        params: Optional[Dict[str, Any]] = None,
    ) -> List[TransactionObject]:
        """
        Get Transactions Using Criteria

        Use this to retrieve all transactions between a date range (this method handles
        pagination automatically unless you specify a limit / offset argument). Returns
        list of Transaction objects. If no query parameters are set, this will return
        transactions for the current calendar month. If either start_date or end_date are
        datetime.datetime objects, they will be reduced to dates. If a string is provided,
        it will be attempted to be parsed as YYYY-MM-DD format.

        Parameters
        ----------
        start_date: Optional[Union[datetime.date, datetime.datetime, str]]
            Denotes the beginning of the time period to fetch transactions for. Defaults
            to beginning of current month. Required if end_date exists. Format: YYYY-MM-DD.
        end_date: Optional[Union[datetime.date, datetime.datetime, str]]
            Denotes the end of the time period you'd like to get transactions for.
            Defaults to end of current month. Required if start_date exists.
        tag_id: Optional[int]
            Filter by tag. Only accepts IDs, not names.
        recurring_id: Optional[int]
            Filter by recurring expense
        plaid_account_id: Optional[int]
            Filter by Plaid account
        category_id: Optional[int]
            Filter by category. Will also match category groups.
        asset_id: Optional[int]
            Filter by asset
        group_id: Optional[int]
            Filter by group_id (if the transaction is part of a specific group)
        is_group: Optional[bool]
            Filter by group (returns transaction groups)
        status: Optional[str]
            Filter by status (Can be cleared or uncleared. For recurring
            transactions, use recurring)
        offset: Optional[int]
            Sets the offset for the records returned (disables
            automatic pagination)
        limit: Optional[int]
            Sets the maximum number of records to return. Defaults to 1000
             (disables automatic pagination)
        debit_as_negative: Optional[bool]
            Pass in true if you'd like expenses to be returned as negative amounts and
            credits as positive amounts. Defaults to false.
        pending: Optional[bool]
            Pass in true if you'd like to include imported transactions with a pending status.
        params: Optional[dict]
            Additional Query String Params

        Returns
        -------
        List[TransactionObject]
            A list of transactions

        Examples
        --------
        Retrieve a list of
        [TransactionObject][lunchable.models.transactions.TransactionObject]

        ```python
        from lunchable import LunchMoney

        lunch = LunchMoney(access_token="xxxxxxx")
        transactions = lunch.get_transactions(start_date="2020-01-01",
                                              end_date="2020-01-31")
        ```
        """
        search_params = _TransactionParamsGet(
            tag_id=tag_id,
            recurring_id=recurring_id,
            plaid_account_id=plaid_account_id,
            category_id=category_id,
            asset_id=asset_id,
            group_id=group_id,
            is_group=is_group,
            status=status,
            offset=offset,
            limit=limit,
            start_date=start_date,
            end_date=end_date,
            debit_as_negative=debit_as_negative,
            pending=pending,
        ).model_dump(exclude_none=True)
        search_params.update(params if params is not None else {})
        auto_paginate = all(
            [
                offset is None,
                search_params.get("offset") is None,
                limit is None,
                search_params.get("limit") is None,
            ]
        )
        transactions = self._get_transactions(
            search_params=search_params,
            paginate=auto_paginate,
        )
        return transactions

    def _get_transactions(
        self,
        search_params: Dict[str, Any],
        existing_transactions: Optional[List[TransactionObject]] = None,
        paginate: bool = True,
    ) -> List[TransactionObject]:
        """
        Paginate Transactions
        """
        existing_transactions = existing_transactions or []
        transaction_response = self.make_request(
            method=self.Methods.GET,
            url_path=APIConfig.LUNCHMONEY_TRANSACTIONS,
            params=search_params,
        )
        transaction_response = _TransactionsResponse.model_validate(
            transaction_response
        )
        existing_transactions.extend(transaction_response.transactions)
        if transaction_response.has_more and paginate:
            search_params["offset"] = len(existing_transactions)
            return self._get_transactions(
                existing_transactions=existing_transactions,
                search_params=search_params,
                paginate=True,
            )
        return existing_transactions

    def get_transaction(
        self, transaction_id: int, debit_as_negative: Optional[bool] = None
    ) -> TransactionObject:
        """
        Get a Transaction by ID

        Parameters
        ----------
        transaction_id: int
            Lunch Money Transaction ID
        debit_as_negative: Optional[bool]
            Pass in true if you'd like expenses to be returned as negative
            amounts and credits as positive amounts. Defaults to false.

        Returns
        -------
        TransactionObject

        Examples
        --------
        Retrieve a single transaction by its ID

        ```python
        from lunchable import LunchMoney

        lunch = LunchMoney(access_token="xxxxxxx")
        transaction = lunch.get_transaction(transaction_id=1234)
        ```

        The above code returns a
        [TransactionObject][lunchable.models.transactions.TransactionObject]
        with ID # 1234 (assuming it exists)
        """
        response_data = self.make_request(
            method=self.Methods.GET,
            url_path=[APIConfig.LUNCHMONEY_TRANSACTIONS, transaction_id],
            params={"debit_as_negative": debit_as_negative}
            if debit_as_negative is not None
            else {},
        )
        return TransactionObject.model_validate(response_data)

    ListOrSingleTransactionUpdateObject = Optional[
        Union[TransactionUpdateObject, TransactionObject]
    ]

    ListOrSingleTransactionInsertObject = Union[
        TransactionObject,
        TransactionInsertObject,
        List[TransactionObject],
        List[TransactionInsertObject],
        List[Union[TransactionObject, TransactionInsertObject]],
    ]

    def update_transaction(
        self,
        transaction_id: int,
        transaction: ListOrSingleTransactionUpdateObject = None,
        split: Optional[List[TransactionSplitObject]] = None,
        debit_as_negative: Optional[bool] = None,
        skip_balance_update: Optional[bool] = None,
    ) -> Dict[str, Any]:
        """
        Update a Transaction

        Use this endpoint to update a single transaction. You may also use this
        to split an existing transaction. If a TransactionObject is provided it will be
        converted into a TransactionUpdateObject.

        PUT https://dev.lunchmoney.app/v1/transactions/:transaction_id

        Parameters
        ----------
        transaction_id: int
            Lunch Money Transaction ID
        transaction: ListOrSingleTransactionUpdateObject
            Object to update with
        split: Optional[List[TransactionSplitObject]]
            Defines the split of a transaction. You may not split an already-split
            transaction, recurring transaction, or group transaction.
        debit_as_negative: Optional[bool]
            If true, will assume negative amount values denote expenses and
            positive amount values denote credits. Defaults to false.
        skip_balance_update: Optional[bool]
            If false, will skip updating balance if an asset_id
            is present for any of the transactions.

        Returns
        -------
        Dict[str, Any]

        Examples
        --------
        Update a transaction with a
        [TransactionUpdateObject][lunchable.models.transactions.TransactionUpdateObject]

        ```python
        from datetime import datetime

        from lunchable import LunchMoney, TransactionUpdateObject

        lunch = LunchMoney(access_token="xxxxxxx")
        transaction_note = f"Updated on {datetime.now()}"
        notes_update = TransactionUpdateObject(notes=transaction_note)
        response = lunch.update_transaction(transaction_id=1234,
                                            transaction=notes_update)
        ```

        Update a
        [TransactionObject][lunchable.models.transactions.TransactionObject]
        with itself

        ```python
        from datetime import datetime, timedelta

        from lunchable import LunchMoney

        lunch = LunchMoney(access_token="xxxxxxx")
        transaction = lunch.get_transaction(transaction_id=1234)

        transaction.notes = f"Updated on {datetime.now()}"
        transaction.date = transaction.date + timedelta(days=1)
        response = lunch.update_transaction(transaction_id=transaction.id,
                                            transaction=transaction)
        ```
        """
        payload = _TransactionUpdateParamsPut(
            split=split,
            debit_as_negative=debit_as_negative,
            skip_balance_update=skip_balance_update,
        ).model_dump(exclude_none=True)
        if transaction is None and split is None:
            raise LunchMoneyError("You must update the transaction or provide a split")
        elif transaction is not None:
            if isinstance(transaction, TransactionObject):
                transaction = transaction.get_update_object()
            payload["transaction"] = transaction.model_dump(exclude_unset=True)
        response_data = self.make_request(
            method=self.Methods.PUT,
            url_path=[APIConfig.LUNCHMONEY_TRANSACTIONS, transaction_id],
            payload=payload,
        )
        return response_data

    def insert_transactions(
        self,
        transactions: ListOrSingleTransactionInsertObject,
        apply_rules: Optional[bool] = None,
        skip_duplicates: Optional[bool] = None,
        debit_as_negative: Optional[bool] = None,
        check_for_recurring: Optional[bool] = None,
        skip_balance_update: Optional[bool] = None,
    ) -> List[int]:
        """
        Create One or Many Lunch Money Transactions

        Use this endpoint to insert many transactions at once. Also accepts
        a single transaction as well. If a TransactionObject is provided it will be
        converted into a TransactionInsertObject.

        https://lunchmoney.dev/#insert-transactions

        Parameters
        ----------
        transactions: ListOrSingleTransactionTypeObject
            Transactions to insert. Either a single TransactionInsertObject object or
            a list of them
        apply_rules: Optional[bool]
            If true, will apply account's existing rules to the inserted transactions.
            Defaults to false.
        skip_duplicates: Optional[bool]
            If true, the system will automatically dedupe based on transaction date,
            payee and amount. Note that deduping by external_id will occur regardless
            of this flag.
        check_for_recurring: Optional[bool]
            if true, will check new transactions for occurrences of new monthly expenses.
            Defaults to false.
        debit_as_negative: Optional[bool]
            If true, will assume negative amount values denote expenses and
            positive amount values denote credits. Defaults to false.
        skip_balance_update: Optional[bool]
            If false, will skip updating balance if an asset_id
            is present for any of the transactions.

        Returns
        -------
        List[int]

        Examples
        --------
        Create a new transaction with a
        [TransactionInsertObject][lunchable.models.transactions.TransactionInsertObject]

        ```python
        from lunchable import LunchMoney, TransactionInsertObject

        lunch = LunchMoney(access_token="xxxxxxx")

        new_transaction = TransactionInsertObject(payee="Example Restaurant",
                                                  amount=120.00,
                                                  notes="Saturday Dinner")
        new_transaction_ids = lunch.insert_transactions(transactions=new_transaction)
        ```
        """
        insert_objects = []
        if not isinstance(transactions, list):
            transactions = [transactions]
        for item in transactions:
            if isinstance(item, TransactionObject):
                insert_objects.append(item.get_insert_object())
            elif isinstance(item, TransactionInsertObject):
                insert_objects.append(item)
            else:
                raise LunchMoneyError(
                    "Only TransactionObjects or TransactionInsertObjects are "
                    "supported by this function."
                )
        payload = _TransactionInsertParamsPost(
            transactions=insert_objects,
            apply_rules=apply_rules,
            skip_duplicates=skip_duplicates,
            check_for_recurring=check_for_recurring,
            debit_as_negative=debit_as_negative,
            skip_balance_update=skip_balance_update,
        ).model_dump(exclude_none=True)
        response_data = self.make_request(
            method=self.Methods.POST,
            url_path=APIConfig.LUNCHMONEY_TRANSACTIONS,
            payload=payload,
        )
        ids: List[int] = response_data["ids"] if response_data else []
        return ids

    def insert_transaction_group(
        self,
        date: datetime.date,
        payee: str,
        transactions: List[int],
        category_id: Optional[int] = None,
        notes: Optional[str] = None,
        tags: Optional[List[int]] = None,
    ) -> int:
        """
        Create a Transaction Group of Two or More Transactions

        Returns the ID of the newly created transaction group

        Parameters
        ----------
        date: datetime.date
            Date for the grouped transaction
        payee: str
            Payee name for the grouped transaction
        category_id: Optional[int]
            Category for the grouped transaction
        notes: Optional[str]
            Notes for the grouped transaction
        tags: Optional[List[int]]
            Array of tag IDs for the grouped transaction
        transactions: Optional[List[int]]
            Array of transaction IDs to be part of the transaction group

        Returns
        -------
        int
        """
        if len(transactions) < 2:
            raise LunchMoneyError(
                "You must include 2 or more transactions " "in the Transaction Group"
            )
        transaction_params = _TransactionGroupParamsPost(
            date=date,
            payee=payee,
            category_id=category_id,
            notes=notes,
            tags=tags,
            transactions=transactions,
        ).model_dump(exclude_none=True)
        response_data = self.make_request(
            method=self.Methods.POST,
            url_path=[
                APIConfig.LUNCHMONEY_TRANSACTIONS,
                APIConfig.LUNCHMONEY_TRANSACTION_GROUPS,
            ],
            payload=transaction_params,
        )
        return response_data

    def remove_transaction_group(self, transaction_group_id: int) -> List[int]:
        """
        Delete a Transaction Group

        Use this method to delete a transaction group. The transactions within the
        group will not be removed.

        Returns the IDs of the transactions that were part of the deleted group

        https://lunchmoney.dev/#delete-transaction-group

        Parameters
        ----------
        transaction_group_id: int
            Transaction Group Identifier

        Returns
        -------
        List[int]
        """
        response_data = self.make_request(
            method=self.Methods.DELETE,
            url_path=[
                APIConfig.LUNCHMONEY_TRANSACTIONS,
                APIConfig.LUNCHMONEY_TRANSACTION_GROUPS,
                transaction_group_id,
            ],
        )
        return response_data["transactions"]

    def unsplit_transactions(
        self, parent_ids: List[int], remove_parents: Optional[bool] = None
    ) -> List[int]:
        """
        Unsplit Transactions

        Use this endpoint to unsplit one or more transactions.

        Returns an array of IDs of deleted transactions

        https://lunchmoney.dev/#unsplit-transactions

        Parameters
        ----------
        parent_ids: List[int]
            Array of transaction IDs to unsplit. If one transaction is unsplittable,
            no transaction will be unsplit.
        remove_parents: Optional[bool]
            If true, deletes the original parent transaction as well. Note,
            this is unreversable!

        Returns
        -------
        List[int]
        """
        response_data = self.make_request(
            method=self.Methods.POST,
            url_path=[APIConfig.LUNCHMONEY_TRANSACTIONS, "unsplit"],
            payload=_TransactionsUnsplitPost(
                parent_ids=parent_ids, remove_parents=remove_parents
            ).model_dump(exclude_none=True),
        )
        return response_data

    def get_transaction_group(self, transaction_id: int) -> TransactionObject:
        """
        Get a Transaction Group

        Parameters
        ----------
        transaction_id: int
            Transaction ID of either the parent or any of the children
            in the transaction group

        Returns
        -------
        TransactionObject
            The transaction group as a `TransactionObject`
        """
        response_data = self.make_request(
            method=self.Methods.GET,
            params={"transaction_id": transaction_id},
            url_path=[
                APIConfig.LUNCHMONEY_TRANSACTIONS,
                APIConfig.LUNCHMONEY_TRANSACTION_GROUPS,
            ],
        )
        return TransactionObject.model_validate(response_data)

get_transaction(transaction_id, debit_as_negative=None) #

Get a Transaction by ID

Parameters:

Name Type Description Default
transaction_id int

Lunch Money Transaction ID

required
debit_as_negative Optional[bool]

Pass in true if you'd like expenses to be returned as negative amounts and credits as positive amounts. Defaults to false.

None

Returns:

Type Description
TransactionObject

Examples:

Retrieve a single transaction by its ID

from lunchable import LunchMoney

lunch = LunchMoney(access_token="xxxxxxx")
transaction = lunch.get_transaction(transaction_id=1234)

The above code returns a TransactionObject with ID # 1234 (assuming it exists)

Source code in lunchable/models/transactions.py
def get_transaction(
    self, transaction_id: int, debit_as_negative: Optional[bool] = None
) -> TransactionObject:
    """
    Get a Transaction by ID

    Parameters
    ----------
    transaction_id: int
        Lunch Money Transaction ID
    debit_as_negative: Optional[bool]
        Pass in true if you'd like expenses to be returned as negative
        amounts and credits as positive amounts. Defaults to false.

    Returns
    -------
    TransactionObject

    Examples
    --------
    Retrieve a single transaction by its ID

    ```python
    from lunchable import LunchMoney

    lunch = LunchMoney(access_token="xxxxxxx")
    transaction = lunch.get_transaction(transaction_id=1234)
    ```

    The above code returns a
    [TransactionObject][lunchable.models.transactions.TransactionObject]
    with ID # 1234 (assuming it exists)
    """
    response_data = self.make_request(
        method=self.Methods.GET,
        url_path=[APIConfig.LUNCHMONEY_TRANSACTIONS, transaction_id],
        params={"debit_as_negative": debit_as_negative}
        if debit_as_negative is not None
        else {},
    )
    return TransactionObject.model_validate(response_data)

get_transaction_group(transaction_id) #

Get a Transaction Group

Parameters:

Name Type Description Default
transaction_id int

Transaction ID of either the parent or any of the children in the transaction group

required

Returns:

Type Description
TransactionObject

The transaction group as a TransactionObject

Source code in lunchable/models/transactions.py
def get_transaction_group(self, transaction_id: int) -> TransactionObject:
    """
    Get a Transaction Group

    Parameters
    ----------
    transaction_id: int
        Transaction ID of either the parent or any of the children
        in the transaction group

    Returns
    -------
    TransactionObject
        The transaction group as a `TransactionObject`
    """
    response_data = self.make_request(
        method=self.Methods.GET,
        params={"transaction_id": transaction_id},
        url_path=[
            APIConfig.LUNCHMONEY_TRANSACTIONS,
            APIConfig.LUNCHMONEY_TRANSACTION_GROUPS,
        ],
    )
    return TransactionObject.model_validate(response_data)

get_transactions(start_date=None, end_date=None, tag_id=None, recurring_id=None, plaid_account_id=None, category_id=None, asset_id=None, group_id=None, is_group=None, status=None, offset=None, limit=None, debit_as_negative=None, pending=None, params=None) #

Get Transactions Using Criteria

Use this to retrieve all transactions between a date range (this method handles pagination automatically unless you specify a limit / offset argument). Returns list of Transaction objects. If no query parameters are set, this will return transactions for the current calendar month. If either start_date or end_date are datetime.datetime objects, they will be reduced to dates. If a string is provided, it will be attempted to be parsed as YYYY-MM-DD format.

Parameters:

Name Type Description Default
start_date Optional[Union[date, datetime, str]]

Denotes the beginning of the time period to fetch transactions for. Defaults to beginning of current month. Required if end_date exists. Format: YYYY-MM-DD.

None
end_date Optional[Union[date, datetime, str]]

Denotes the end of the time period you'd like to get transactions for. Defaults to end of current month. Required if start_date exists.

None
tag_id Optional[int]

Filter by tag. Only accepts IDs, not names.

None
recurring_id Optional[int]

Filter by recurring expense

None
plaid_account_id Optional[int]

Filter by Plaid account

None
category_id Optional[int]

Filter by category. Will also match category groups.

None
asset_id Optional[int]

Filter by asset

None
group_id Optional[int]

Filter by group_id (if the transaction is part of a specific group)

None
is_group Optional[bool]

Filter by group (returns transaction groups)

None
status Optional[str]

Filter by status (Can be cleared or uncleared. For recurring transactions, use recurring)

None
offset Optional[int]

Sets the offset for the records returned (disables automatic pagination)

None
limit Optional[int]

Sets the maximum number of records to return. Defaults to 1000 (disables automatic pagination)

None
debit_as_negative Optional[bool]

Pass in true if you'd like expenses to be returned as negative amounts and credits as positive amounts. Defaults to false.

None
pending Optional[bool]

Pass in true if you'd like to include imported transactions with a pending status.

None
params Optional[Dict[str, Any]]

Additional Query String Params

None

Returns:

Type Description
List[TransactionObject]

A list of transactions

Examples:

Retrieve a list of TransactionObject

from lunchable import LunchMoney

lunch = LunchMoney(access_token="xxxxxxx")
transactions = lunch.get_transactions(start_date="2020-01-01",
                                      end_date="2020-01-31")
Source code in lunchable/models/transactions.py
def get_transactions(
    self,
    start_date: Optional[Union[datetime.date, datetime.datetime, str]] = None,
    end_date: Optional[Union[datetime.date, datetime.datetime, str]] = None,
    tag_id: Optional[int] = None,
    recurring_id: Optional[int] = None,
    plaid_account_id: Optional[int] = None,
    category_id: Optional[int] = None,
    asset_id: Optional[int] = None,
    group_id: Optional[int] = None,
    is_group: Optional[bool] = None,
    status: Optional[str] = None,
    offset: Optional[int] = None,
    limit: Optional[int] = None,
    debit_as_negative: Optional[bool] = None,
    pending: Optional[bool] = None,
    params: Optional[Dict[str, Any]] = None,
) -> List[TransactionObject]:
    """
    Get Transactions Using Criteria

    Use this to retrieve all transactions between a date range (this method handles
    pagination automatically unless you specify a limit / offset argument). Returns
    list of Transaction objects. If no query parameters are set, this will return
    transactions for the current calendar month. If either start_date or end_date are
    datetime.datetime objects, they will be reduced to dates. If a string is provided,
    it will be attempted to be parsed as YYYY-MM-DD format.

    Parameters
    ----------
    start_date: Optional[Union[datetime.date, datetime.datetime, str]]
        Denotes the beginning of the time period to fetch transactions for. Defaults
        to beginning of current month. Required if end_date exists. Format: YYYY-MM-DD.
    end_date: Optional[Union[datetime.date, datetime.datetime, str]]
        Denotes the end of the time period you'd like to get transactions for.
        Defaults to end of current month. Required if start_date exists.
    tag_id: Optional[int]
        Filter by tag. Only accepts IDs, not names.
    recurring_id: Optional[int]
        Filter by recurring expense
    plaid_account_id: Optional[int]
        Filter by Plaid account
    category_id: Optional[int]
        Filter by category. Will also match category groups.
    asset_id: Optional[int]
        Filter by asset
    group_id: Optional[int]
        Filter by group_id (if the transaction is part of a specific group)
    is_group: Optional[bool]
        Filter by group (returns transaction groups)
    status: Optional[str]
        Filter by status (Can be cleared or uncleared. For recurring
        transactions, use recurring)
    offset: Optional[int]
        Sets the offset for the records returned (disables
        automatic pagination)
    limit: Optional[int]
        Sets the maximum number of records to return. Defaults to 1000
         (disables automatic pagination)
    debit_as_negative: Optional[bool]
        Pass in true if you'd like expenses to be returned as negative amounts and
        credits as positive amounts. Defaults to false.
    pending: Optional[bool]
        Pass in true if you'd like to include imported transactions with a pending status.
    params: Optional[dict]
        Additional Query String Params

    Returns
    -------
    List[TransactionObject]
        A list of transactions

    Examples
    --------
    Retrieve a list of
    [TransactionObject][lunchable.models.transactions.TransactionObject]

    ```python
    from lunchable import LunchMoney

    lunch = LunchMoney(access_token="xxxxxxx")
    transactions = lunch.get_transactions(start_date="2020-01-01",
                                          end_date="2020-01-31")
    ```
    """
    search_params = _TransactionParamsGet(
        tag_id=tag_id,
        recurring_id=recurring_id,
        plaid_account_id=plaid_account_id,
        category_id=category_id,
        asset_id=asset_id,
        group_id=group_id,
        is_group=is_group,
        status=status,
        offset=offset,
        limit=limit,
        start_date=start_date,
        end_date=end_date,
        debit_as_negative=debit_as_negative,
        pending=pending,
    ).model_dump(exclude_none=True)
    search_params.update(params if params is not None else {})
    auto_paginate = all(
        [
            offset is None,
            search_params.get("offset") is None,
            limit is None,
            search_params.get("limit") is None,
        ]
    )
    transactions = self._get_transactions(
        search_params=search_params,
        paginate=auto_paginate,
    )
    return transactions

insert_transaction_group(date, payee, transactions, category_id=None, notes=None, tags=None) #

Create a Transaction Group of Two or More Transactions

Returns the ID of the newly created transaction group

Parameters:

Name Type Description Default
date date

Date for the grouped transaction

required
payee str

Payee name for the grouped transaction

required
category_id Optional[int]

Category for the grouped transaction

None
notes Optional[str]

Notes for the grouped transaction

None
tags Optional[List[int]]

Array of tag IDs for the grouped transaction

None
transactions List[int]

Array of transaction IDs to be part of the transaction group

required

Returns:

Type Description
int
Source code in lunchable/models/transactions.py
def insert_transaction_group(
    self,
    date: datetime.date,
    payee: str,
    transactions: List[int],
    category_id: Optional[int] = None,
    notes: Optional[str] = None,
    tags: Optional[List[int]] = None,
) -> int:
    """
    Create a Transaction Group of Two or More Transactions

    Returns the ID of the newly created transaction group

    Parameters
    ----------
    date: datetime.date
        Date for the grouped transaction
    payee: str
        Payee name for the grouped transaction
    category_id: Optional[int]
        Category for the grouped transaction
    notes: Optional[str]
        Notes for the grouped transaction
    tags: Optional[List[int]]
        Array of tag IDs for the grouped transaction
    transactions: Optional[List[int]]
        Array of transaction IDs to be part of the transaction group

    Returns
    -------
    int
    """
    if len(transactions) < 2:
        raise LunchMoneyError(
            "You must include 2 or more transactions " "in the Transaction Group"
        )
    transaction_params = _TransactionGroupParamsPost(
        date=date,
        payee=payee,
        category_id=category_id,
        notes=notes,
        tags=tags,
        transactions=transactions,
    ).model_dump(exclude_none=True)
    response_data = self.make_request(
        method=self.Methods.POST,
        url_path=[
            APIConfig.LUNCHMONEY_TRANSACTIONS,
            APIConfig.LUNCHMONEY_TRANSACTION_GROUPS,
        ],
        payload=transaction_params,
    )
    return response_data

insert_transactions(transactions, apply_rules=None, skip_duplicates=None, debit_as_negative=None, check_for_recurring=None, skip_balance_update=None) #

Create One or Many Lunch Money Transactions

Use this endpoint to insert many transactions at once. Also accepts a single transaction as well. If a TransactionObject is provided it will be converted into a TransactionInsertObject.

https://lunchmoney.dev/#insert-transactions

Parameters:

Name Type Description Default
transactions ListOrSingleTransactionInsertObject

Transactions to insert. Either a single TransactionInsertObject object or a list of them

required
apply_rules Optional[bool]

If true, will apply account's existing rules to the inserted transactions. Defaults to false.

None
skip_duplicates Optional[bool]

If true, the system will automatically dedupe based on transaction date, payee and amount. Note that deduping by external_id will occur regardless of this flag.

None
check_for_recurring Optional[bool]

if true, will check new transactions for occurrences of new monthly expenses. Defaults to false.

None
debit_as_negative Optional[bool]

If true, will assume negative amount values denote expenses and positive amount values denote credits. Defaults to false.

None
skip_balance_update Optional[bool]

If false, will skip updating balance if an asset_id is present for any of the transactions.

None

Returns:

Type Description
List[int]

Examples:

Create a new transaction with a TransactionInsertObject

from lunchable import LunchMoney, TransactionInsertObject

lunch = LunchMoney(access_token="xxxxxxx")

new_transaction = TransactionInsertObject(payee="Example Restaurant",
                                          amount=120.00,
                                          notes="Saturday Dinner")
new_transaction_ids = lunch.insert_transactions(transactions=new_transaction)
Source code in lunchable/models/transactions.py
def insert_transactions(
    self,
    transactions: ListOrSingleTransactionInsertObject,
    apply_rules: Optional[bool] = None,
    skip_duplicates: Optional[bool] = None,
    debit_as_negative: Optional[bool] = None,
    check_for_recurring: Optional[bool] = None,
    skip_balance_update: Optional[bool] = None,
) -> List[int]:
    """
    Create One or Many Lunch Money Transactions

    Use this endpoint to insert many transactions at once. Also accepts
    a single transaction as well. If a TransactionObject is provided it will be
    converted into a TransactionInsertObject.

    https://lunchmoney.dev/#insert-transactions

    Parameters
    ----------
    transactions: ListOrSingleTransactionTypeObject
        Transactions to insert. Either a single TransactionInsertObject object or
        a list of them
    apply_rules: Optional[bool]
        If true, will apply account's existing rules to the inserted transactions.
        Defaults to false.
    skip_duplicates: Optional[bool]
        If true, the system will automatically dedupe based on transaction date,
        payee and amount. Note that deduping by external_id will occur regardless
        of this flag.
    check_for_recurring: Optional[bool]
        if true, will check new transactions for occurrences of new monthly expenses.
        Defaults to false.
    debit_as_negative: Optional[bool]
        If true, will assume negative amount values denote expenses and
        positive amount values denote credits. Defaults to false.
    skip_balance_update: Optional[bool]
        If false, will skip updating balance if an asset_id
        is present for any of the transactions.

    Returns
    -------
    List[int]

    Examples
    --------
    Create a new transaction with a
    [TransactionInsertObject][lunchable.models.transactions.TransactionInsertObject]

    ```python
    from lunchable import LunchMoney, TransactionInsertObject

    lunch = LunchMoney(access_token="xxxxxxx")

    new_transaction = TransactionInsertObject(payee="Example Restaurant",
                                              amount=120.00,
                                              notes="Saturday Dinner")
    new_transaction_ids = lunch.insert_transactions(transactions=new_transaction)
    ```
    """
    insert_objects = []
    if not isinstance(transactions, list):
        transactions = [transactions]
    for item in transactions:
        if isinstance(item, TransactionObject):
            insert_objects.append(item.get_insert_object())
        elif isinstance(item, TransactionInsertObject):
            insert_objects.append(item)
        else:
            raise LunchMoneyError(
                "Only TransactionObjects or TransactionInsertObjects are "
                "supported by this function."
            )
    payload = _TransactionInsertParamsPost(
        transactions=insert_objects,
        apply_rules=apply_rules,
        skip_duplicates=skip_duplicates,
        check_for_recurring=check_for_recurring,
        debit_as_negative=debit_as_negative,
        skip_balance_update=skip_balance_update,
    ).model_dump(exclude_none=True)
    response_data = self.make_request(
        method=self.Methods.POST,
        url_path=APIConfig.LUNCHMONEY_TRANSACTIONS,
        payload=payload,
    )
    ids: List[int] = response_data["ids"] if response_data else []
    return ids

remove_transaction_group(transaction_group_id) #

Delete a Transaction Group

Use this method to delete a transaction group. The transactions within the group will not be removed.

Returns the IDs of the transactions that were part of the deleted group

https://lunchmoney.dev/#delete-transaction-group

Parameters:

Name Type Description Default
transaction_group_id int

Transaction Group Identifier

required

Returns:

Type Description
List[int]
Source code in lunchable/models/transactions.py
def remove_transaction_group(self, transaction_group_id: int) -> List[int]:
    """
    Delete a Transaction Group

    Use this method to delete a transaction group. The transactions within the
    group will not be removed.

    Returns the IDs of the transactions that were part of the deleted group

    https://lunchmoney.dev/#delete-transaction-group

    Parameters
    ----------
    transaction_group_id: int
        Transaction Group Identifier

    Returns
    -------
    List[int]
    """
    response_data = self.make_request(
        method=self.Methods.DELETE,
        url_path=[
            APIConfig.LUNCHMONEY_TRANSACTIONS,
            APIConfig.LUNCHMONEY_TRANSACTION_GROUPS,
            transaction_group_id,
        ],
    )
    return response_data["transactions"]

unsplit_transactions(parent_ids, remove_parents=None) #

Unsplit Transactions

Use this endpoint to unsplit one or more transactions.

Returns an array of IDs of deleted transactions

https://lunchmoney.dev/#unsplit-transactions

Parameters:

Name Type Description Default
parent_ids List[int]

Array of transaction IDs to unsplit. If one transaction is unsplittable, no transaction will be unsplit.

required
remove_parents Optional[bool]

If true, deletes the original parent transaction as well. Note, this is unreversable!

None

Returns:

Type Description
List[int]
Source code in lunchable/models/transactions.py
def unsplit_transactions(
    self, parent_ids: List[int], remove_parents: Optional[bool] = None
) -> List[int]:
    """
    Unsplit Transactions

    Use this endpoint to unsplit one or more transactions.

    Returns an array of IDs of deleted transactions

    https://lunchmoney.dev/#unsplit-transactions

    Parameters
    ----------
    parent_ids: List[int]
        Array of transaction IDs to unsplit. If one transaction is unsplittable,
        no transaction will be unsplit.
    remove_parents: Optional[bool]
        If true, deletes the original parent transaction as well. Note,
        this is unreversable!

    Returns
    -------
    List[int]
    """
    response_data = self.make_request(
        method=self.Methods.POST,
        url_path=[APIConfig.LUNCHMONEY_TRANSACTIONS, "unsplit"],
        payload=_TransactionsUnsplitPost(
            parent_ids=parent_ids, remove_parents=remove_parents
        ).model_dump(exclude_none=True),
    )
    return response_data

update_transaction(transaction_id, transaction=None, split=None, debit_as_negative=None, skip_balance_update=None) #

Update a Transaction

Use this endpoint to update a single transaction. You may also use this to split an existing transaction. If a TransactionObject is provided it will be converted into a TransactionUpdateObject.

PUT https://dev.lunchmoney.app/v1/transactions/:transaction_id

Parameters:

Name Type Description Default
transaction_id int

Lunch Money Transaction ID

required
transaction ListOrSingleTransactionUpdateObject

Object to update with

None
split Optional[List[TransactionSplitObject]]

Defines the split of a transaction. You may not split an already-split transaction, recurring transaction, or group transaction.

None
debit_as_negative Optional[bool]

If true, will assume negative amount values denote expenses and positive amount values denote credits. Defaults to false.

None
skip_balance_update Optional[bool]

If false, will skip updating balance if an asset_id is present for any of the transactions.

None

Returns:

Type Description
Dict[str, Any]

Examples:

Update a transaction with a TransactionUpdateObject

from datetime import datetime

from lunchable import LunchMoney, TransactionUpdateObject

lunch = LunchMoney(access_token="xxxxxxx")
transaction_note = f"Updated on {datetime.now()}"
notes_update = TransactionUpdateObject(notes=transaction_note)
response = lunch.update_transaction(transaction_id=1234,
                                    transaction=notes_update)

Update a TransactionObject with itself

from datetime import datetime, timedelta

from lunchable import LunchMoney

lunch = LunchMoney(access_token="xxxxxxx")
transaction = lunch.get_transaction(transaction_id=1234)

transaction.notes = f"Updated on {datetime.now()}"
transaction.date = transaction.date + timedelta(days=1)
response = lunch.update_transaction(transaction_id=transaction.id,
                                    transaction=transaction)
Source code in lunchable/models/transactions.py
def update_transaction(
    self,
    transaction_id: int,
    transaction: ListOrSingleTransactionUpdateObject = None,
    split: Optional[List[TransactionSplitObject]] = None,
    debit_as_negative: Optional[bool] = None,
    skip_balance_update: Optional[bool] = None,
) -> Dict[str, Any]:
    """
    Update a Transaction

    Use this endpoint to update a single transaction. You may also use this
    to split an existing transaction. If a TransactionObject is provided it will be
    converted into a TransactionUpdateObject.

    PUT https://dev.lunchmoney.app/v1/transactions/:transaction_id

    Parameters
    ----------
    transaction_id: int
        Lunch Money Transaction ID
    transaction: ListOrSingleTransactionUpdateObject
        Object to update with
    split: Optional[List[TransactionSplitObject]]
        Defines the split of a transaction. You may not split an already-split
        transaction, recurring transaction, or group transaction.
    debit_as_negative: Optional[bool]
        If true, will assume negative amount values denote expenses and
        positive amount values denote credits. Defaults to false.
    skip_balance_update: Optional[bool]
        If false, will skip updating balance if an asset_id
        is present for any of the transactions.

    Returns
    -------
    Dict[str, Any]

    Examples
    --------
    Update a transaction with a
    [TransactionUpdateObject][lunchable.models.transactions.TransactionUpdateObject]

    ```python
    from datetime import datetime

    from lunchable import LunchMoney, TransactionUpdateObject

    lunch = LunchMoney(access_token="xxxxxxx")
    transaction_note = f"Updated on {datetime.now()}"
    notes_update = TransactionUpdateObject(notes=transaction_note)
    response = lunch.update_transaction(transaction_id=1234,
                                        transaction=notes_update)
    ```

    Update a
    [TransactionObject][lunchable.models.transactions.TransactionObject]
    with itself

    ```python
    from datetime import datetime, timedelta

    from lunchable import LunchMoney

    lunch = LunchMoney(access_token="xxxxxxx")
    transaction = lunch.get_transaction(transaction_id=1234)

    transaction.notes = f"Updated on {datetime.now()}"
    transaction.date = transaction.date + timedelta(days=1)
    response = lunch.update_transaction(transaction_id=transaction.id,
                                        transaction=transaction)
    ```
    """
    payload = _TransactionUpdateParamsPut(
        split=split,
        debit_as_negative=debit_as_negative,
        skip_balance_update=skip_balance_update,
    ).model_dump(exclude_none=True)
    if transaction is None and split is None:
        raise LunchMoneyError("You must update the transaction or provide a split")
    elif transaction is not None:
        if isinstance(transaction, TransactionObject):
            transaction = transaction.get_update_object()
        payload["transaction"] = transaction.model_dump(exclude_unset=True)
    response_data = self.make_request(
        method=self.Methods.PUT,
        url_path=[APIConfig.LUNCHMONEY_TRANSACTIONS, transaction_id],
        payload=payload,
    )
    return response_data