### Run Tests Source: https://github.com/raphaelm/python-sepaxml/blob/master/README.rst Instructions for running the project's tests using pytest. Ensure development requirements are installed. ```bash pip install -r requirements_dev.txt py.test tests ``` -------------------------------- ### Use sepadd Compatibility Alias for SepaDD Source: https://context7.com/raphaelm/python-sepaxml/llms.txt The `sepadd` package re-exports `SepaDD` for backward compatibility. This example demonstrates initializing `SepaDD` with configuration and adding a direct debit payment. ```python # Equivalent to: from sepaxml import SepaDD from sepadd import SepaDD sepa = SepaDD({ "name": "My Organisation", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "batch": False, "creditor_id": "DE26ZZZ00000000000", "currency": "EUR", }, schema="pain.008.001.02") sepa.add_payment({ "name": "Customer A", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "amount": 500, "type": "OOFF", "collection_date": datetime.date.today(), "mandate_id": "OOFF-001", "mandate_date": datetime.date.today(), "description": "One-off payment", }) print(sepa.export(validate=True)) ``` -------------------------------- ### Generate SEPA XML Transfer Source: https://github.com/raphaelm/python-sepaxml/blob/master/README.rst Example of creating a SepaTransfer object, adding payment details, and exporting the XML. Ensure datetime and uuid are imported. ```python import datetime import uuid from sepaxml import SepaTransfer config = { "name": "Sender Name", "IBAN": "NL99BANK0000000000", "BIC": "BANKNL2A", "currency": "EUR", "batch_booking": True, "creditor_identifier": "MD-99999-99999", "address": { "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, } sepa = SepaTransfer(config, clean=True) payment = { "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "amount": 5000, # in cents "execution_date": datetime.date.today() + datetime.timedelta(days=2), "description": "Test transaction", # "endtoend_id": str(uuid.uuid1()).replace("-", ""), # optional "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, } sepa.add_payment(payment) print(sepa.export(validate=True)) ``` -------------------------------- ### Generate SEPA Direct Debit XML Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Use SepaDD to create Customer Direct Debit Initiation XML documents. Configure creditor details and add payments with mandate information. Amounts are specified in integer cents. The export method validates the XML against the schema. ```python from sepaxml import SepaDD import datetime # --- Creditor configuration --- config = { "name": "Acme GmbH", "IBAN": "DE89370400440532013000", "BIC": "COBADEFFXXX", # required for pain.008.001.02; optional for newer schemas "batch": True, # True → one PmtInf block per (type, date); False → one per transaction "creditor_id": "DE98ZZZ09999999999", # SEPA creditor identifier issued by your bank "currency": "EUR", # Optional: override the initiating party name / ID shown in the GroupHeader # "initiating_party": "Acme Holding", # "initiating_party_id": "DE98ZZZ09999999998", # Optional: instrument – default is CORE (B2C); use "B2B" for business-to-business # "instrument": "B2B", # Optional: postal address (required by some banks / countries) "address": { "address_type": "ADDR", # ADDR | PBOX | HOME | BIZZ | MLTO | DLVY "street_name": "Unter den Linden", "building_number": "21", "postcode": "10117", "town": "Berlin", "country": "DE", "lines": ["c/o Finance Dept"], }, # Optional: ultimate creditor (required by some financial institutions) "ultimate_creditor": { "name": "Real Creditor SA", "BIC_or_BEI": "REALDEFFXXX", "id": "98765432100001", "id_scheme_name": "SIRET", }, } # Use pain.008.001.09 (newer schema – BIC not required) sepa = SepaDD(config, schema="pain.008.001.09", clean=True) # --- Add a first direct-debit payment (FRST = first collection under mandate) --- sepa.add_payment({ "name": "Max Mustermann", "IBAN": "NL91ABNA0417164300", # "BIC": "ABNANL2A", # optional for pain.008.001.09+ "amount": 2599, # €25.99 expressed in cents "type": "FRST", # FRST | RCUR | OOFF | FNAL "collection_date": datetime.date(2024, 9, 1), "mandate_id": "MNDT-2024-001", "mandate_date": datetime.date(2024, 1, 15), "description": "Mitgliedsbeitrag September 2024", # "endtoend_id": "E2E-20240901-001", # auto-generated if omitted "address": { "street_name": "Musterstrasse", "building_number": "5", "postcode": "80331", "town": "Muenchen", "country": "DE", }, }) # --- Add a recurring payment on the same collection date (batched together) --- sepa.add_payment({ "name": "Erika Musterfrau", "IBAN": "DE27200400600540400400", "amount": 1500, # €15.00 "type": "RCUR", "collection_date": datetime.date(2024, 9, 1), "mandate_id": "MNDT-2023-042", "mandate_date": datetime.date(2023, 3, 10), "description": "Mitgliedsbeitrag September 2024", }) # --- Export and validate against the XSD schema --- try: xml_bytes = sepa.export(validate=True, pretty_print=True) print(xml_bytes.decode()) # Write to file: with open("direct_debit.xml", "wb") as f: f.write(xml_bytes) except Exception as e: print(f"Validation error: {e}") # Expected output structure (abbreviated): # # # # # 20240901120000-a1b2c3d4e5f6 # 2 # 40.99 # ... # # # ... # ``` -------------------------------- ### Generate SEPA Direct Debit XML Source: https://github.com/raphaelm/python-sepaxml/blob/master/README.rst Use SepaDD to create SEPA Direct Debit XML files. Configure creditor details and add payment instructions. The 'clean' parameter removes optional fields if not provided. ```python from sepaxml import SepaDD import datetime, uuid config = { # "msg_id": "", # If your bank require a specific format for MsgId, you can optionnaly set it up here. Default will be randomly generated with timestamp followed by a random value. "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "batch": True, "creditor_id": "DE26ZZZ00000000000", # supplied by your bank or financial authority "currency": "EUR", # ISO 4217 # "instrument": "B2B", # - default is CORE (B2C) "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, # "initiating_party": "John Doe", # optional name of the initiator of the payment, required by some banks. default to ''name' # "initiating_party_id": "DE26ZZZ00000000002", # optional, supplied by your bank or financial authority. default to 'creditor_id' "ultimate_creditor": { # The ultimate_creditor and all of its fields are optional but in some financial institution they are required "name": "Real Creditor", "BIC_or_BEI": "REALNL2A", "id": "12345678900001", # can be a local official id or the creditor_id "id_scheme_name": "SIRET", # proprietary scheme of the id provided (i.e. SEPA, SIRET...) }, } sepa = SepaDD(config, schema="pain.008.001.02", clean=True) payment = { "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "amount": 5000, # in cents "type": "RCUR", # FRST,RCUR,OOFF,FNAL "collection_date": datetime.date.today(), "mandate_id": "1234", "mandate_date": datetime.date.today(), "description": "Test transaction", # "endtoend_id": str(uuid.uuid1()).replace("-", ""), # autogenerated if obmitted "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, # "initiating_party": "John Doe", # optional name of the initiator of the payment, required by some banks. default to ''name' # "initiating_party_id": "DE26ZZZ00000000002", # optional, supplied by your bank or financial authority. default to 'creditor_id' } sepa.add_payment(payment) print(sepa.export(validate=True)) ``` -------------------------------- ### Select Supported SEPA Schemas Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Instantiate `SepaDD` or `SepaTransfer` with a `schema` keyword argument to target specific ISO 20022 XSD versions. The library automatically adjusts element names like `BIC` vs `BICFI` based on the chosen schema. ```python from sepaxml import SepaDD, SepaTransfer # Direct Debit schemas SepaDD(config, schema="pain.008.001.02") # legacy – BIC required in config and payments SepaDD(config, schema="pain.008.001.08") # BIC optional SepaDD(config, schema="pain.008.001.09") # BIC optional SepaDD(config, schema="pain.008.001.10") # BIC optional (latest) # Credit Transfer schemas SepaTransfer(config, schema="pain.001.001.03") # legacy SepaTransfer(config, schema="pain.001.001.09") # ReqdExctnDt wrapped in
SepaTransfer(config, schema="pain.001.001.10") SepaTransfer(config, schema="pain.001.001.11") # latest # Newer schemas use BICFI element instead of BIC for financial institution IDs # The library switches element names automatically based on the chosen schema. ``` -------------------------------- ### Generate SEPA Credit Transfer XML Source: https://github.com/raphaelm/python-sepaxml/blob/master/README.rst Use SepaTransfer to create SEPA Credit Transfer XML files. Configure sender details and add payment instructions. The 'domestic' flag can be set for non-SEPA transfers like those in CH/LI. ```python from sepaxml import SepaTransfer import datetime, uuid config = { # "msg_id": "", # If your bank require a specific message_id format, you can set it up here. Default will be randomly generated with timestamp followed by a random value. "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "batch": True, # For non-SEPA transfers, set "domestic" to True, necessary e.g. for CH/LI "currency": "EUR", # ISO 4217 "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", ``` -------------------------------- ### Supported Schemas Source: https://context7.com/raphaelm/python-sepaxml/llms.txt The SepaXML library supports various ISO 20022 XSD schemas for both Direct Debit (SepaDD) and Credit Transfer (SepaTransfer). The `schema` keyword argument selects the target XSD, which influences XML namespaces and element names (e.g., `BIC` vs `BICFI`). ```APIDOC ## Supported Schemas Both classes accept a `schema` keyword that selects the ISO 20022 XSD to target. The schema name also determines the XML namespace and certain element names (e.g., `BIC` vs `BICFI`). ```python from sepaxml import SepaDD, SepaTransfer # Direct Debit schemas SepaDD(config, schema="pain.008.001.02") # legacy – BIC required in config and payments SepaDD(config, schema="pain.008.001.08") # BIC optional SepaDD(config, schema="pain.008.001.09") # BIC optional SepaDD(config, schema="pain.008.001.10") # BIC optional (latest) # Credit Transfer schemas SepaTransfer(config, schema="pain.001.001.03") # legacy SepaTransfer(config, schema="pain.001.001.09") # ReqdExctnDt wrapped in
SepaTransfer(config, schema="pain.001.001.10") SepaTransfer(config, schema="pain.001.001.11") # latest # Newer schemas use BICFI element instead of BIC for financial institution IDs # The library switches element names automatically based on the chosen schema. ``` ``` -------------------------------- ### Sort Imports Source: https://github.com/raphaelm/python-sepaxml/blob/master/README.rst Command to automatically sort Python imports using isort. This is required by CI. ```bash pip install isort isort -rc . ``` -------------------------------- ### SepaTransfer.add_payment() Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Appends a single credit-transfer transaction to the SepaTransfer object. Requires essential fields like name, IBAN, amount, execution_date, and description. Optional fields like BIC, endtoend_id, currency, and address can also be provided. ```APIDOC ## `SepaTransfer.add_payment()` — Credit Transfer Payment Fields `add_payment()` for `SepaTransfer` validates and appends one credit-transfer transaction. The `execution_date` must be a `datetime.date` instance. ```python sepa.add_payment({ # ── Required ────────────────────────────────────────────────────────── "name": "Beneficiary Name", "IBAN": "FR7630006000011234567890189", "amount": 75050, # integer cents (75050 = €750.50) "execution_date": datetime.date(2024, 9, 15), "description": "Payment for services rendered", # ── Optional ────────────────────────────────────────────────────────── "BIC": "BNPAFRPPXXX", # creditor agent BIC "endtoend_id": "PO-2024-0099", # max 35 chars; 'NOTPROVIDED' if absent "currency": "EUR", # per-payment currency override "address": { "address_type": "BIZZ", "street_name": "Rue de la Paix", "building_number": "3", "postcode": "75001", "town": "Paris", "country": "FR", "lines": [], }, }) ``` ``` -------------------------------- ### Create SEPA Credit Transfer XML Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Generates a SEPA Credit Transfer XML document. Supports different schemas and domestic transfer configurations. Ensure correct currency and date formats. ```python from sepaxml import SepaTransfer import datetime # --- Debtor (sender) configuration --- config = { "name": "Acme GmbH", "IBAN": "DE89370400440532013000", "BIC": "COBADEFFXXX", "batch": True, "currency": "EUR", # Set domestic=True for non-SEPA transfers (CH/LI): # "domestic": True, # "msg_id": "ACME-20240901-001", # custom message ID (max 35 chars); auto-generated if omitted "address": { "street_name": "Unter den Linden", "building_number": "21", "postcode": "10117", "town": "Berlin", "country": "DE", }, } sepa = SepaTransfer(config, schema="pain.001.001.03", clean=True) # --- Add a transfer to a supplier --- sepa.add_payment({ "name": "Supplier AG", "IBAN": "AT611904300234573201", "BIC": "BKAUATWW", "amount": 125000, # €1,250.00 in cents "execution_date": datetime.date.today() + datetime.timedelta(days=1), "description": "Invoice INV-2024-0815", "endtoend_id": "INV-2024-0815", # optional; 'NOTPROVIDED' used if omitted "address": { "street_name": "Ringstrasse", "building_number": "1", "postcode": "1010", "town": "Wien", "country": "AT", }, }) # --- Add a second transfer with a different currency per payment --- sepa.add_payment({ "name": "Freelancer Ltd", "IBAN": "GB29NWBK60161331926819", "BIC": "NWBKGB2L", "amount": 50000, # €500.00 "execution_date": datetime.date.today() + datetime.timedelta(days=1), "description": "Consulting fee Q3-2024", "currency": "EUR", # overrides config currency per-payment }) xml_bytes = sepa.export(validate=True, pretty_print=False) with open("credit_transfer.xml", "wb") as f: f.write(xml_bytes) # --- Domestic (non-SEPA) transfer example for Switzerland --- sepa_ch = SepaTransfer({ "name": "Swiss Corp AG", "IBAN": "CH4912345123456789012", "batch": True, "domestic": True, "currency": "CHF", }, schema="pain.001.001.03") sepa_ch.add_payment({ "name": "Local Vendor GmbH", "IBAN": "CH6911111222222222222", "amount": 30000, # CHF 300.00 "execution_date": datetime.date.today(), "description": "Office supplies", }) xml_ch = sepa_ch.export(validate=True) ``` -------------------------------- ### sepadd Compatibility Alias Source: https://context7.com/raphaelm/python-sepaxml/llms.txt The `sepadd` top-level package re-exports `SepaDD` for backward compatibility, allowing codebases that previously depended on the `PySepaDD` package name to continue functioning. ```APIDOC ## `sepadd` Compatibility Alias A `sepadd` top-level package re-exports `SepaDD` for backwards compatibility with codebases that depended on the original `PySepaDD` package name. ```python # Equivalent to: from sepaxml import SepaDD from sepadd import SepaDD sepa = SepaDD({ "name": "My Organisation", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "batch": False, "creditor_id": "DE26ZZZ00000000000", "currency": "EUR", }, schema="pain.008.001.02") sepa.add_payment({ "name": "Customer A", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "amount": 500, "type": "OOFF", "collection_date": datetime.date.today(), "mandate_id": "OOFF-001", "mandate_date": datetime.date.today(), "description": "One-off payment", }) print(sepa.export(validate=True)) ``` ``` -------------------------------- ### export() Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Finalizes batches, calculates totals, serializes to UTF-8 bytes, and optionally validates the XML output against the embedded XSD schema. This method should be called exactly once after all payments have been added. ```APIDOC ## `export()` — Generate and Validate the XML Document `export()` finalises all batches, calculates the group-level `CtrlSum` and `NbOfTxs` totals, serialises the XML to UTF-8 bytes, and optionally validates the output against the embedded XSD schema. Call this exactly **once** after all payments have been added. ```python # Basic export with schema validation (default) xml_bytes = sepa.export(validate=True) # Export without validation (e.g. for debugging invalid data) xml_bytes = sepa.export(validate=False) # Pretty-printed output using xml.dom.minidom xml_bytes = sepa.export(validate=True, pretty_print=True) print(xml_bytes.decode("utf-8")) # Catch validation errors from sepaxml.validation import ValidationError try: xml_bytes = sepa.export(validate=True) except ValidationError as e: print("SEPA XML failed XSD validation:", e) except Exception as e: print("Config or payment data error:", e) # Returns: bytes – UTF-8 encoded XML starting with the XML declaration # b'...' ``` ``` -------------------------------- ### SepaTransfer - SEPA Credit Transfer Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Creates a CstmrCdtTrfInitn (Customer Credit Transfer Initiation) XML document. Supports various schemas and domestic transfer configurations. ```APIDOC ## SepaTransfer `SepaTransfer` creates a `CstmrCdtTrfInitn` (Customer Credit Transfer Initiation) XML document. The default schema is `pain.001.001.03`; newer schemas (`pain.001.001.09` / `.10` / `.11`) are also supported. Setting `domestic=True` in the config omits the `SEPA` element, which is required for non-SEPA domestic transfers (e.g., Switzerland/Liechtenstein). ### Configuration Options: - `name` (string): Sender's name. - `IBAN` (string): Sender's IBAN. - `BIC` (string): Sender's BIC. - `batch` (boolean): Whether to use batch processing. - `currency` (string): Default currency for transfers (e.g., 'EUR', 'CHF'). - `domestic` (boolean, optional): Set to `True` for non-SEPA domestic transfers. - `msg_id` (string, optional): Custom message ID (max 35 chars). - `address` (object, optional): Sender's address details. - `street_name` (string) - `building_number` (string) - `postcode` (string) - `town` (string) - `country` (string) ### `add_payment()` Method: Adds a single payment to the transfer. #### Parameters: - `name` (string): Payee's name. - `IBAN` (string): Payee's IBAN. - `BIC` (string): Payee's BIC. - `amount` (integer): Transfer amount in cents. - `execution_date` (datetime.date): Desired execution date. - `description` (string): Payment description. - `endtoend_id` (string, optional): End-to-end identification for the payment. - `address` (object, optional): Payee's address details. ### `export()` Method: Exports the generated XML data. #### Parameters: - `validate` (boolean, optional): Whether to validate the XML against the schema. - `pretty_print` (boolean, optional): Whether to format the XML for readability. ### Example Usage: ```python from sepaxml import SepaTransfer import datetime config = { "name": "Acme GmbH", "IBAN": "DE89370400440532013000", "BIC": "COBADEFFXXX", "batch": True, "currency": "EUR", "address": { "street_name": "Unter den Linden", "building_number": "21", "postcode": "10117", "town": "Berlin", "country": "DE", }, } sepa = SepaTransfer(config, schema="pain.001.001.03", clean=True) sepa.add_payment({ "name": "Supplier AG", "IBAN": "AT611904300234573201", "BIC": "BKAUATWW", "amount": 125000, # €1,250.00 in cents "execution_date": datetime.date.today() + datetime.timedelta(days=1), "description": "Invoice INV-2024-0815", "endtoend_id": "INV-2024-0815", "address": { "street_name": "Ringstrasse", "building_number": "1", "postcode": "1010", "town": "Wien", "country": "AT", }, }) xml_bytes = sepa.export(validate=True, pretty_print=False) with open("credit_transfer.xml", "wb") as f: f.write(xml_bytes) # Domestic (non-SEPA) transfer example for Switzerland sepa_ch = SepaTransfer({ "name": "Swiss Corp AG", "IBAN": "CH4912345123456789012", "batch": True, "domestic": True, "currency": "CHF", }, schema="pain.001.001.03") sepa_ch.add_payment({ "name": "Local Vendor GmbH", "IBAN": "CH6911111222222222222", "amount": 30000, # CHF 300.00 "execution_date": datetime.date.today(), "description": "Office supplies", }) xml_ch = sepa_ch.export(validate=True) ``` ``` -------------------------------- ### Export and Validate SEPA XML Document Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Finalizes batches, calculates totals, serializes to UTF-8 bytes, and optionally validates against the XSD schema. Call this exactly once after all payments are added. Use `validate=False` for debugging. ```python # Basic export with schema validation (default) xml_bytes = sepa.export(validate=True) ``` ```python # Export without validation (e.g. for debugging invalid data) xml_bytes = sepa.export(validate=False) ``` ```python # Pretty-printed output using xml.dom.minidom xml_bytes = sepa.export(validate=True, pretty_print=True) print(xml_bytes.decode("utf-8")) ``` ```python # Catch validation errors from sepaxml.validation import ValidationError try: xml_bytes = sepa.export(validate=True) except ValidationError as e: print("SEPA XML failed XSD validation:", e) except Exception as e: print("Config or payment data error:", e) ``` ```python # Returns: bytes – UTF-8 encoded XML starting with the XML declaration # b'...' ``` -------------------------------- ### Add Credit Transfer Payment to SepaTransfer Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Appends a single credit-transfer transaction to a SepaTransfer object. The `execution_date` must be a `datetime.date` instance. Ensure all required fields like name, IBAN, amount, execution_date, and description are provided. ```python sepa.add_payment({ # ── Required ────────────────────────────────────────────────────────── "name": "Beneficiary Name", "IBAN": "FR7630006000011234567890189", "amount": 75050, # integer cents (75050 = €750.50) "execution_date": datetime.date(2024, 9, 15), "description": "Payment for services rendered", # ── Optional ────────────────────────────────────────────────────────── "BIC": "BNPAFRPPXXX", # creditor agent BIC "endtoend_id": "PO-2024-0099", # max 35 chars; 'NOTPROVIDED' if absent "currency": "EUR", # per-payment currency override "address": { "address_type": "BIZZ", "street_name": "Rue de la Paix", "building_number": "3", "postcode": "75001", "town": "Paris", "country": "FR", "lines": [], }, }) ``` -------------------------------- ### SepaDD.add_payment() - Direct Debit Payment Fields Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Appends one direct-debit transaction to the SEPA XML document. All amounts are integers representing cents. ```APIDOC ## `SepaTransfer.add_payment()` for Direct Debit `add_payment()` validates and appends one direct-debit transaction. All amounts are integers (cents). ### Parameters: #### Required: - `name` (string): Debtor name (truncated to 70 chars with `clean=True`). - `IBAN` (string): Debtor's IBAN. - `amount` (integer): Amount in cents (e.g., 999 for €9.99). - `type` (string): Transaction type ('FRST', 'RCUR', 'OOFF', 'FNAL'). - `collection_date` (datetime.date): Date of collection. - `mandate_id` (string): Unique identifier for the mandate. - `mandate_date` (datetime.date): Date the mandate was signed. - `description` (string): Payment description (truncated to 140 chars with `clean=True`). #### Optional: - `BIC` (string): Debtor's BIC (required for `pain.008.001.02`, optional otherwise). - `endtoend_id` (string): End-to-end reference (max 35 chars). - `currency` (string): Overrides config-level currency for this payment. - `address` (object): Postal address of the debtor (required by some banks). - `address_type` (string, e.g., 'ADDR') - `department` (string) - `subdepartment` (string or None) - `street_name` (string) - `building_number` (string) - `postcode` (string) - `town` (string) - `country` (string) - `country_subdivision` (string or None) - `lines` (list of strings): Free-form address lines. ### Example Usage: ```python sepa.add_payment({ "name": "Debtor Full Name", "IBAN": "DE27200400600540400400", "amount": 999, "type": "FRST", "collection_date": datetime.date(2024, 10, 1), "mandate_id": "MANDATE-001", "mandate_date": datetime.date(2022, 5, 20), "description": "Monthly subscription", "BIC": "DEUTDEDB", "endtoend_id": "E2E-REF-001", "currency": "EUR", "address": { "address_type": "ADDR", "department": "Accounting", "subdepartment": None, "street_name": "Beispielstrasse", "building_number": "12", "postcode": "60329", "town": "Frankfurt", "country": "DE", "country_subdivision": None, "lines": ["Floor 3"], }, }) ``` ``` -------------------------------- ### Add SEPA Direct Debit Payment Source: https://context7.com/raphaelm/python-sepaxml/llms.txt Appends a direct-debit transaction to a SEPA document. Amounts are in cents. Ensure all required fields like type, mandate details, and dates are provided. ```python sepa.add_payment({ # ── Required ────────────────────────────────────────────────────────── "name": "Debtor Full Name", # debtor name, truncated to 70 chars with clean=True "IBAN": "DE27200400600540400400", "amount": 999, # integer, cents (999 = €9.99) "type": "FRST", # FRST | RCUR | OOFF | FNAL "collection_date": datetime.date(2024, 10, 1), # datetime.date instance "mandate_id": "MANDATE-001", "mandate_date": datetime.date(2022, 5, 20), # date mandate was signed "description": "Monthly subscription", # truncated to 140 chars with clean=True # ── Optional ────────────────────────────────────────────────────────── "BIC": "DEUTDEDB", # required for pain.008.001.02, optional otherwise "endtoend_id": "E2E-REF-001", # max 35 chars; auto-generated if absent "currency": "EUR", # overrides config-level currency for this payment "address": { "address_type": "ADDR", "department": "Accounting", "subdepartment": None, "street_name": "Beispielstrasse", "building_number": "12", "postcode": "60329", "town": "Frankfurt", "country": "DE", "country_subdivision": None, "lines": ["Floor 3"], # free-form address lines (AdrLine elements) }, }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.