factpulse 2.0.37__py3-none-any.whl → 3.0.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of factpulse might be problematic. Click here for more details.

Files changed (262) hide show
  1. factpulse/__init__.py +265 -197
  2. factpulse/api/__init__.py +5 -4
  3. factpulse/api/afnorpdppa_api.py +34 -34
  4. factpulse/api/afnorpdppa_directory_service_api.py +59 -59
  5. factpulse/api/afnorpdppa_flow_service_api.py +23 -23
  6. factpulse/api/chorus_pro_api.py +211 -211
  7. factpulse/api/document_conversion_api.py +1506 -0
  8. factpulse/api/{sant_api.py → health_api.py} +22 -22
  9. factpulse/api/invoice_processing_api.py +3437 -0
  10. factpulse/api/{vrification_pdfxml_api.py → pdfxml_verification_api.py} +240 -240
  11. factpulse/api/{utilisateur_api.py → user_api.py} +17 -17
  12. factpulse/api_client.py +3 -3
  13. factpulse/configuration.py +3 -3
  14. factpulse/exceptions.py +2 -2
  15. factpulse/models/__init__.py +128 -95
  16. factpulse/models/acknowledgment_status.py +38 -0
  17. factpulse/models/additional_document.py +115 -0
  18. factpulse/models/afnor_credentials.py +106 -0
  19. factpulse/models/afnor_destination.py +127 -0
  20. factpulse/models/afnor_health_check_response.py +91 -0
  21. factpulse/models/afnor_result.py +105 -0
  22. factpulse/models/allowance_charge.py +147 -0
  23. factpulse/models/allowance_reason_code.py +42 -0
  24. factpulse/models/allowance_total_amount.py +145 -0
  25. factpulse/models/amount.py +139 -0
  26. factpulse/models/amount_due.py +139 -0
  27. factpulse/models/api_error.py +5 -5
  28. factpulse/models/async_task_status.py +97 -0
  29. factpulse/models/base_amount.py +145 -0
  30. factpulse/models/bounding_box_schema.py +10 -10
  31. factpulse/models/celery_status.py +40 -0
  32. factpulse/models/certificate_info_response.py +24 -24
  33. factpulse/models/charge_total_amount.py +145 -0
  34. factpulse/models/chorus_pro_destination.py +108 -0
  35. factpulse/models/chorus_pro_result.py +101 -0
  36. factpulse/models/contact.py +113 -0
  37. factpulse/models/convert_error_response.py +105 -0
  38. factpulse/models/convert_pending_input_response.py +114 -0
  39. factpulse/models/convert_resume_request.py +87 -0
  40. factpulse/models/convert_success_response.py +126 -0
  41. factpulse/models/convert_validation_failed_response.py +120 -0
  42. factpulse/models/delivery_party.py +121 -0
  43. factpulse/models/destination.py +27 -27
  44. factpulse/models/document_type_info.py +91 -0
  45. factpulse/models/electronic_address.py +90 -0
  46. factpulse/models/enriched_invoice_info.py +133 -0
  47. factpulse/models/error_level.py +2 -2
  48. factpulse/models/error_source.py +2 -2
  49. factpulse/models/extraction_info.py +93 -0
  50. factpulse/models/factur_x_invoice.py +320 -0
  51. factpulse/models/factur_x_profile.py +39 -0
  52. factpulse/models/factur_xpdf_info.py +91 -0
  53. factpulse/models/facture_electronique_rest_api_schemas_chorus_pro_chorus_pro_credentials.py +95 -0
  54. factpulse/models/facture_electronique_rest_api_schemas_processing_chorus_pro_credentials.py +115 -0
  55. factpulse/models/field_status.py +40 -0
  56. factpulse/models/file_info.py +94 -0
  57. factpulse/models/files_info.py +106 -0
  58. factpulse/models/flow_direction.py +37 -0
  59. factpulse/models/flow_profile.py +38 -0
  60. factpulse/models/flow_summary.py +131 -0
  61. factpulse/models/flow_syntax.py +40 -0
  62. factpulse/models/flow_type.py +40 -0
  63. factpulse/models/generate_certificate_request.py +26 -26
  64. factpulse/models/generate_certificate_response.py +15 -15
  65. factpulse/models/get_chorus_pro_id_request.py +100 -0
  66. factpulse/models/get_chorus_pro_id_response.py +98 -0
  67. factpulse/models/get_invoice_request.py +98 -0
  68. factpulse/models/get_invoice_response.py +142 -0
  69. factpulse/models/get_structure_request.py +100 -0
  70. factpulse/models/get_structure_response.py +142 -0
  71. factpulse/models/global_allowance_amount.py +139 -0
  72. factpulse/models/gross_unit_price.py +145 -0
  73. factpulse/models/http_validation_error.py +2 -2
  74. factpulse/models/incoming_invoice.py +196 -0
  75. factpulse/models/incoming_supplier.py +144 -0
  76. factpulse/models/invoice_format.py +38 -0
  77. factpulse/models/invoice_line.py +354 -0
  78. factpulse/models/invoice_line_allowance_amount.py +145 -0
  79. factpulse/models/invoice_note.py +94 -0
  80. factpulse/models/invoice_references.py +194 -0
  81. factpulse/models/invoice_status.py +96 -0
  82. factpulse/models/invoice_totals.py +177 -0
  83. factpulse/models/invoice_totals_prepayment.py +145 -0
  84. factpulse/models/invoice_type_code.py +51 -0
  85. factpulse/models/invoicing_framework.py +110 -0
  86. factpulse/models/invoicing_framework_code.py +39 -0
  87. factpulse/models/line_net_amount.py +145 -0
  88. factpulse/models/line_total_amount.py +145 -0
  89. factpulse/models/mandatory_note_schema.py +124 -0
  90. factpulse/models/manual_rate.py +139 -0
  91. factpulse/models/manual_vat_rate.py +139 -0
  92. factpulse/models/missing_field.py +107 -0
  93. factpulse/models/operation_nature.py +49 -0
  94. factpulse/models/output_format.py +37 -0
  95. factpulse/models/page_dimensions_schema.py +89 -0
  96. factpulse/models/payee.py +168 -0
  97. factpulse/models/payment_card.py +99 -0
  98. factpulse/models/payment_means.py +41 -0
  99. factpulse/models/pdf_validation_result_api.py +169 -0
  100. factpulse/models/pdp_credentials.py +15 -15
  101. factpulse/models/percentage.py +145 -0
  102. factpulse/models/postal_address.py +134 -0
  103. factpulse/models/price_allowance_amount.py +145 -0
  104. factpulse/models/price_basis_quantity.py +145 -0
  105. factpulse/models/processing_options.py +94 -0
  106. factpulse/models/product_characteristic.py +89 -0
  107. factpulse/models/product_classification.py +101 -0
  108. factpulse/models/quantity.py +139 -0
  109. factpulse/models/recipient.py +167 -0
  110. factpulse/models/rounding_amount.py +145 -0
  111. factpulse/models/scheme_id.py +10 -4
  112. factpulse/models/search_flow_request.py +143 -0
  113. factpulse/models/search_flow_response.py +101 -0
  114. factpulse/models/search_services_response.py +101 -0
  115. factpulse/models/search_structure_request.py +119 -0
  116. factpulse/models/search_structure_response.py +101 -0
  117. factpulse/models/signature_info.py +6 -6
  118. factpulse/models/signature_info_api.py +122 -0
  119. factpulse/models/signature_parameters.py +133 -0
  120. factpulse/models/simplified_invoice_data.py +124 -0
  121. factpulse/models/structure_info.py +14 -14
  122. factpulse/models/structure_parameters.py +91 -0
  123. factpulse/models/structure_service.py +93 -0
  124. factpulse/models/submission_mode.py +38 -0
  125. factpulse/models/submit_complete_invoice_request.py +116 -0
  126. factpulse/models/submit_complete_invoice_response.py +145 -0
  127. factpulse/models/submit_flow_request.py +123 -0
  128. factpulse/models/submit_flow_response.py +109 -0
  129. factpulse/models/submit_gross_amount.py +139 -0
  130. factpulse/models/submit_invoice_request.py +176 -0
  131. factpulse/models/submit_invoice_response.py +103 -0
  132. factpulse/models/submit_net_amount.py +139 -0
  133. factpulse/models/submit_vat_amount.py +139 -0
  134. factpulse/models/supplementary_attachment.py +95 -0
  135. factpulse/models/supplier.py +225 -0
  136. factpulse/models/task_response.py +87 -0
  137. factpulse/models/tax_representative.py +95 -0
  138. factpulse/models/taxable_amount.py +139 -0
  139. factpulse/models/total_gross_amount.py +139 -0
  140. factpulse/models/total_net_amount.py +139 -0
  141. factpulse/models/total_vat_amount.py +139 -0
  142. factpulse/models/unit_net_price.py +139 -0
  143. factpulse/models/unit_of_measure.py +41 -0
  144. factpulse/models/validation_error.py +2 -2
  145. factpulse/models/validation_error_detail.py +6 -6
  146. factpulse/models/validation_error_loc_inner.py +2 -2
  147. factpulse/models/validation_error_response.py +87 -0
  148. factpulse/models/validation_info.py +105 -0
  149. factpulse/models/validation_success_response.py +87 -0
  150. factpulse/models/vat_accounting_code.py +39 -0
  151. factpulse/models/vat_amount.py +139 -0
  152. factpulse/models/vat_category.py +44 -0
  153. factpulse/models/vat_line.py +140 -0
  154. factpulse/models/vat_point_date_code.py +38 -0
  155. factpulse/models/vat_rate.py +145 -0
  156. factpulse/models/verification_success_response.py +135 -0
  157. factpulse/models/verified_field_schema.py +129 -0
  158. factpulse/rest.py +2 -2
  159. factpulse-3.0.7.dist-info/METADATA +292 -0
  160. factpulse-3.0.7.dist-info/RECORD +168 -0
  161. factpulse_helpers/__init__.py +34 -34
  162. factpulse_helpers/client.py +1019 -795
  163. factpulse_helpers/exceptions.py +68 -68
  164. factpulse/api/traitement_facture_api.py +0 -3437
  165. factpulse/models/adresse_electronique.py +0 -90
  166. factpulse/models/adresse_postale.py +0 -120
  167. factpulse/models/cadre_de_facturation.py +0 -110
  168. factpulse/models/categorie_tva.py +0 -44
  169. factpulse/models/champ_verifie_schema.py +0 -129
  170. factpulse/models/chorus_pro_credentials.py +0 -95
  171. factpulse/models/code_cadre_facturation.py +0 -39
  172. factpulse/models/code_raison_reduction.py +0 -42
  173. factpulse/models/consulter_facture_request.py +0 -98
  174. factpulse/models/consulter_facture_response.py +0 -142
  175. factpulse/models/consulter_structure_request.py +0 -100
  176. factpulse/models/consulter_structure_response.py +0 -142
  177. factpulse/models/credentials_afnor.py +0 -106
  178. factpulse/models/credentials_chorus_pro.py +0 -115
  179. factpulse/models/destinataire.py +0 -130
  180. factpulse/models/destination_afnor.py +0 -127
  181. factpulse/models/destination_chorus_pro.py +0 -108
  182. factpulse/models/dimension_page_schema.py +0 -89
  183. factpulse/models/direction_flux.py +0 -37
  184. factpulse/models/donnees_facture_simplifiees.py +0 -124
  185. factpulse/models/facture_enrichie_info.py +0 -133
  186. factpulse/models/facture_entrante.py +0 -196
  187. factpulse/models/facture_factur_x.py +0 -183
  188. factpulse/models/flux_resume.py +0 -131
  189. factpulse/models/format_facture.py +0 -38
  190. factpulse/models/format_sortie.py +0 -37
  191. factpulse/models/fournisseur.py +0 -153
  192. factpulse/models/fournisseur_entrant.py +0 -144
  193. factpulse/models/information_signature_api.py +0 -122
  194. factpulse/models/ligne_de_poste.py +0 -183
  195. factpulse/models/ligne_de_poste_montant_remise_ht.py +0 -145
  196. factpulse/models/ligne_de_poste_taux_tva_manuel.py +0 -145
  197. factpulse/models/ligne_de_tva.py +0 -132
  198. factpulse/models/mode_depot.py +0 -38
  199. factpulse/models/mode_paiement.py +0 -41
  200. factpulse/models/montant_a_payer.py +0 -139
  201. factpulse/models/montant_base_ht.py +0 -139
  202. factpulse/models/montant_ht_total.py +0 -139
  203. factpulse/models/montant_remise_globale_ttc.py +0 -139
  204. factpulse/models/montant_total.py +0 -133
  205. factpulse/models/montant_total_acompte.py +0 -145
  206. factpulse/models/montant_total_ligne_ht.py +0 -139
  207. factpulse/models/montant_ttc_total.py +0 -139
  208. factpulse/models/montant_tva.py +0 -139
  209. factpulse/models/montant_tva_ligne.py +0 -139
  210. factpulse/models/montant_tva_total.py +0 -139
  211. factpulse/models/montant_unitaire_ht.py +0 -139
  212. factpulse/models/nature_operation.py +0 -49
  213. factpulse/models/note.py +0 -94
  214. factpulse/models/note_obligatoire_schema.py +0 -124
  215. factpulse/models/obtenir_id_chorus_pro_request.py +0 -100
  216. factpulse/models/obtenir_id_chorus_pro_response.py +0 -98
  217. factpulse/models/options_processing.py +0 -94
  218. factpulse/models/parametres_signature.py +0 -133
  219. factpulse/models/parametres_structure.py +0 -91
  220. factpulse/models/pdf_factur_x_info.py +0 -91
  221. factpulse/models/piece_jointe_complementaire.py +0 -95
  222. factpulse/models/profil_api.py +0 -39
  223. factpulse/models/profil_flux.py +0 -38
  224. factpulse/models/quantite.py +0 -139
  225. factpulse/models/rechercher_services_response.py +0 -101
  226. factpulse/models/rechercher_structure_request.py +0 -119
  227. factpulse/models/rechercher_structure_response.py +0 -101
  228. factpulse/models/references.py +0 -124
  229. factpulse/models/reponse_healthcheck_afnor.py +0 -91
  230. factpulse/models/reponse_recherche_flux.py +0 -101
  231. factpulse/models/reponse_soumission_flux.py +0 -109
  232. factpulse/models/reponse_tache.py +0 -87
  233. factpulse/models/reponse_validation_erreur.py +0 -87
  234. factpulse/models/reponse_validation_succes.py +0 -87
  235. factpulse/models/reponse_verification_succes.py +0 -135
  236. factpulse/models/requete_recherche_flux.py +0 -143
  237. factpulse/models/requete_soumission_flux.py +0 -123
  238. factpulse/models/resultat_afnor.py +0 -105
  239. factpulse/models/resultat_chorus_pro.py +0 -101
  240. factpulse/models/resultat_validation_pdfapi.py +0 -169
  241. factpulse/models/service_structure.py +0 -93
  242. factpulse/models/soumettre_facture_complete_request.py +0 -116
  243. factpulse/models/soumettre_facture_complete_response.py +0 -145
  244. factpulse/models/soumettre_facture_request.py +0 -176
  245. factpulse/models/soumettre_facture_response.py +0 -103
  246. factpulse/models/statut_acquittement.py +0 -38
  247. factpulse/models/statut_celery.py +0 -40
  248. factpulse/models/statut_champ_api.py +0 -40
  249. factpulse/models/statut_facture.py +0 -96
  250. factpulse/models/statut_tache.py +0 -97
  251. factpulse/models/syntaxe_flux.py +0 -40
  252. factpulse/models/tauxmanuel.py +0 -139
  253. factpulse/models/type_document.py +0 -40
  254. factpulse/models/type_facture.py +0 -37
  255. factpulse/models/type_flux.py +0 -40
  256. factpulse/models/type_tva.py +0 -39
  257. factpulse/models/unite.py +0 -41
  258. factpulse-2.0.37.dist-info/METADATA +0 -292
  259. factpulse-2.0.37.dist-info/RECORD +0 -134
  260. {factpulse-2.0.37.dist-info → factpulse-3.0.7.dist-info}/WHEEL +0 -0
  261. {factpulse-2.0.37.dist-info → factpulse-3.0.7.dist-info}/licenses/LICENSE +0 -0
  262. {factpulse-2.0.37.dist-info → factpulse-3.0.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,320 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ FactPulse REST API
5
+
6
+ REST API for electronic invoicing in France: Factur-X, AFNOR PDP/PA, electronic signatures. ## 🎯 Main Features ### 📄 Factur-X Invoice Generation - **Formats**: XML only or PDF/A-3 with embedded XML - **Profiles**: MINIMUM, BASIC, EN16931, EXTENDED - **Standards**: EN 16931 (EU directive 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Simplified Format**: Generation from SIRET + auto-enrichment (Chorus Pro API + Business Search) ### ✅ Validation and Compliance - **XML Validation**: Schematron (45 to 210+ rules depending on profile) - **PDF Validation**: PDF/A-3, Factur-X XMP metadata, electronic signatures - **VeraPDF**: Strict PDF/A validation (146+ ISO 19005-3 rules) - **Asynchronous Processing**: Celery support for heavy validations (VeraPDF) ### 📡 AFNOR PDP/PA Integration (XP Z12-013) - **Flow Submission**: Send invoices to Partner Dematerialization Platforms - **Flow Search**: View submitted invoices - **Download**: Retrieve PDF/A-3 with XML - **Directory Service**: Company search (SIREN/SIRET) - **Multi-client**: Support for multiple PDP configs per user (stored credentials or zero-storage) ### ✍️ PDF Electronic Signature - **Standards**: PAdES-B-B, PAdES-B-T (RFC 3161 timestamping), PAdES-B-LT (long-term archival) - **eIDAS Levels**: SES (self-signed), AdES (commercial CA), QES (QTSP) - **Validation**: Cryptographic integrity and certificate verification - **Certificate Generation**: Self-signed X.509 certificates for testing ### 🔄 Asynchronous Processing - **Celery**: Asynchronous generation, validation and signing - **Polling**: Status tracking via `/tasks/{task_id}/status` - **No timeout**: Ideal for large files or heavy validations ## 🔒 Authentication All requests require a **JWT token** in the Authorization header: ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### How to obtain a JWT token? #### 🔑 Method 1: `/api/token/` API (Recommended) **URL:** `https://www.factpulse.fr/api/token/` This method is **recommended** for integration in your applications and CI/CD workflows. **Prerequisites:** Having set a password on your account **For users registered via email/password:** - You already have a password, use it directly **For users registered via OAuth (Google/GitHub):** - You must first set a password at: https://www.factpulse.fr/accounts/password/set/ - Once the password is created, you can use the API **Request example:** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\" }' ``` **Optional `client_uid` parameter:** To select credentials for a specific client (PA/PDP, Chorus Pro, signing certificates), add `client_uid`: ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\", \"client_uid\": \"550e8400-e29b-41d4-a716-446655440000\" }' ``` The `client_uid` will be included in the JWT and allow the API to automatically use: - AFNOR/PDP credentials configured for this client - Chorus Pro credentials configured for this client - Electronic signature certificates configured for this client **Response:** ```json { \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\", // Access token (validity: 30 min) \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\" // Refresh token (validity: 7 days) } ``` **Advantages:** - ✅ Full automation (CI/CD, scripts) - ✅ Programmatic token management - ✅ Refresh token support for automatic access renewal - ✅ Easy integration in any language/tool #### 🖥️ Method 2: Dashboard Generation (Alternative) **URL:** https://www.factpulse.fr/dashboard/ This method is suitable for quick tests or occasional use via the graphical interface. **How it works:** - Log in to the dashboard - Use the \"Generate Test Token\" or \"Generate Production Token\" buttons - Works for **all** users (OAuth and email/password), without requiring a password **Token types:** - **Test Token**: 24h validity, 1000 calls/day quota (free) - **Production Token**: 7 days validity, quota based on your plan **Advantages:** - ✅ Quick for API testing - ✅ No password required - ✅ Simple visual interface **Disadvantages:** - ❌ Requires manual action - ❌ No refresh token - ❌ Less suited for automation ### 📚 Full Documentation For more information on authentication and API usage: https://www.factpulse.fr/documentation-api/
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from factpulse.models.additional_document import AdditionalDocument
23
+ from factpulse.models.allowance_charge import AllowanceCharge
24
+ from factpulse.models.delivery_party import DeliveryParty
25
+ from factpulse.models.invoice_line import InvoiceLine
26
+ from factpulse.models.invoice_note import InvoiceNote
27
+ from factpulse.models.invoice_references import InvoiceReferences
28
+ from factpulse.models.invoice_totals import InvoiceTotals
29
+ from factpulse.models.invoicing_framework import InvoicingFramework
30
+ from factpulse.models.payee import Payee
31
+ from factpulse.models.payment_card import PaymentCard
32
+ from factpulse.models.recipient import Recipient
33
+ from factpulse.models.submission_mode import SubmissionMode
34
+ from factpulse.models.supplementary_attachment import SupplementaryAttachment
35
+ from factpulse.models.supplier import Supplier
36
+ from factpulse.models.tax_representative import TaxRepresentative
37
+ from factpulse.models.vat_line import VATLine
38
+ from typing import Optional, Set
39
+ from typing_extensions import Self
40
+
41
+ class FacturXInvoice(BaseModel):
42
+ """
43
+ Data model for an invoice to be converted to Factur-X.
44
+ """ # noqa: E501
45
+ invoice_number: StrictStr
46
+ payment_due_date: StrictStr
47
+ invoice_date: Optional[StrictStr] = None
48
+ submission_mode: SubmissionMode
49
+ recipient: Recipient
50
+ supplier: Supplier
51
+ invoicing_framework: InvoicingFramework
52
+ references: InvoiceReferences
53
+ totals: InvoiceTotals
54
+ invoice_lines: Optional[List[InvoiceLine]] = None
55
+ vat_lines: Optional[List[VATLine]] = None
56
+ notes: Optional[List[InvoiceNote]] = None
57
+ comment: Optional[StrictStr] = None
58
+ current_user_id: Optional[StrictInt] = None
59
+ supplementary_attachments: Optional[List[SupplementaryAttachment]] = None
60
+ payee: Optional[Payee] = None
61
+ delivery_party: Optional[DeliveryParty] = None
62
+ tax_representative: Optional[TaxRepresentative] = None
63
+ delivery_date: Optional[StrictStr] = None
64
+ billing_period_start: Optional[StrictStr] = None
65
+ billing_period_end: Optional[StrictStr] = None
66
+ payment_reference: Optional[StrictStr] = None
67
+ creditor_reference_id: Optional[StrictStr] = None
68
+ direct_debit_mandate_id: Optional[StrictStr] = None
69
+ debtor_iban: Optional[StrictStr] = None
70
+ payment_terms: Optional[StrictStr] = None
71
+ allowances_charges: Optional[List[AllowanceCharge]] = None
72
+ additional_documents: Optional[List[AdditionalDocument]] = None
73
+ buyer_accounting_reference: Optional[StrictStr] = None
74
+ payment_card: Optional[PaymentCard] = None
75
+ __properties: ClassVar[List[str]] = ["invoice_number", "payment_due_date", "invoice_date", "submission_mode", "recipient", "supplier", "invoicing_framework", "references", "totals", "invoice_lines", "vat_lines", "notes", "comment", "current_user_id", "supplementary_attachments", "payee", "delivery_party", "tax_representative", "delivery_date", "billing_period_start", "billing_period_end", "payment_reference", "creditor_reference_id", "direct_debit_mandate_id", "debtor_iban", "payment_terms", "allowances_charges", "additional_documents", "buyer_accounting_reference", "payment_card"]
76
+
77
+ model_config = ConfigDict(
78
+ populate_by_name=True,
79
+ validate_assignment=True,
80
+ protected_namespaces=(),
81
+ )
82
+
83
+
84
+ def to_str(self) -> str:
85
+ """Returns the string representation of the model using alias"""
86
+ return pprint.pformat(self.model_dump(by_alias=True))
87
+
88
+ def to_json(self) -> str:
89
+ """Returns the JSON representation of the model using alias"""
90
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
91
+ return json.dumps(self.to_dict())
92
+
93
+ @classmethod
94
+ def from_json(cls, json_str: str) -> Optional[Self]:
95
+ """Create an instance of FacturXInvoice from a JSON string"""
96
+ return cls.from_dict(json.loads(json_str))
97
+
98
+ def to_dict(self) -> Dict[str, Any]:
99
+ """Return the dictionary representation of the model using alias.
100
+
101
+ This has the following differences from calling pydantic's
102
+ `self.model_dump(by_alias=True)`:
103
+
104
+ * `None` is only added to the output dict for nullable fields that
105
+ were set at model initialization. Other fields with value `None`
106
+ are ignored.
107
+ """
108
+ excluded_fields: Set[str] = set([
109
+ ])
110
+
111
+ _dict = self.model_dump(
112
+ by_alias=True,
113
+ exclude=excluded_fields,
114
+ exclude_none=True,
115
+ )
116
+ # override the default output from pydantic by calling `to_dict()` of recipient
117
+ if self.recipient:
118
+ _dict['recipient'] = self.recipient.to_dict()
119
+ # override the default output from pydantic by calling `to_dict()` of supplier
120
+ if self.supplier:
121
+ _dict['supplier'] = self.supplier.to_dict()
122
+ # override the default output from pydantic by calling `to_dict()` of invoicing_framework
123
+ if self.invoicing_framework:
124
+ _dict['invoicing_framework'] = self.invoicing_framework.to_dict()
125
+ # override the default output from pydantic by calling `to_dict()` of references
126
+ if self.references:
127
+ _dict['references'] = self.references.to_dict()
128
+ # override the default output from pydantic by calling `to_dict()` of totals
129
+ if self.totals:
130
+ _dict['totals'] = self.totals.to_dict()
131
+ # override the default output from pydantic by calling `to_dict()` of each item in invoice_lines (list)
132
+ _items = []
133
+ if self.invoice_lines:
134
+ for _item_invoice_lines in self.invoice_lines:
135
+ if _item_invoice_lines:
136
+ _items.append(_item_invoice_lines.to_dict())
137
+ _dict['invoice_lines'] = _items
138
+ # override the default output from pydantic by calling `to_dict()` of each item in vat_lines (list)
139
+ _items = []
140
+ if self.vat_lines:
141
+ for _item_vat_lines in self.vat_lines:
142
+ if _item_vat_lines:
143
+ _items.append(_item_vat_lines.to_dict())
144
+ _dict['vat_lines'] = _items
145
+ # override the default output from pydantic by calling `to_dict()` of each item in notes (list)
146
+ _items = []
147
+ if self.notes:
148
+ for _item_notes in self.notes:
149
+ if _item_notes:
150
+ _items.append(_item_notes.to_dict())
151
+ _dict['notes'] = _items
152
+ # override the default output from pydantic by calling `to_dict()` of each item in supplementary_attachments (list)
153
+ _items = []
154
+ if self.supplementary_attachments:
155
+ for _item_supplementary_attachments in self.supplementary_attachments:
156
+ if _item_supplementary_attachments:
157
+ _items.append(_item_supplementary_attachments.to_dict())
158
+ _dict['supplementary_attachments'] = _items
159
+ # override the default output from pydantic by calling `to_dict()` of payee
160
+ if self.payee:
161
+ _dict['payee'] = self.payee.to_dict()
162
+ # override the default output from pydantic by calling `to_dict()` of delivery_party
163
+ if self.delivery_party:
164
+ _dict['delivery_party'] = self.delivery_party.to_dict()
165
+ # override the default output from pydantic by calling `to_dict()` of tax_representative
166
+ if self.tax_representative:
167
+ _dict['tax_representative'] = self.tax_representative.to_dict()
168
+ # override the default output from pydantic by calling `to_dict()` of each item in allowances_charges (list)
169
+ _items = []
170
+ if self.allowances_charges:
171
+ for _item_allowances_charges in self.allowances_charges:
172
+ if _item_allowances_charges:
173
+ _items.append(_item_allowances_charges.to_dict())
174
+ _dict['allowances_charges'] = _items
175
+ # override the default output from pydantic by calling `to_dict()` of each item in additional_documents (list)
176
+ _items = []
177
+ if self.additional_documents:
178
+ for _item_additional_documents in self.additional_documents:
179
+ if _item_additional_documents:
180
+ _items.append(_item_additional_documents.to_dict())
181
+ _dict['additional_documents'] = _items
182
+ # override the default output from pydantic by calling `to_dict()` of payment_card
183
+ if self.payment_card:
184
+ _dict['payment_card'] = self.payment_card.to_dict()
185
+ # set to None if comment (nullable) is None
186
+ # and model_fields_set contains the field
187
+ if self.comment is None and "comment" in self.model_fields_set:
188
+ _dict['comment'] = None
189
+
190
+ # set to None if current_user_id (nullable) is None
191
+ # and model_fields_set contains the field
192
+ if self.current_user_id is None and "current_user_id" in self.model_fields_set:
193
+ _dict['current_user_id'] = None
194
+
195
+ # set to None if supplementary_attachments (nullable) is None
196
+ # and model_fields_set contains the field
197
+ if self.supplementary_attachments is None and "supplementary_attachments" in self.model_fields_set:
198
+ _dict['supplementary_attachments'] = None
199
+
200
+ # set to None if payee (nullable) is None
201
+ # and model_fields_set contains the field
202
+ if self.payee is None and "payee" in self.model_fields_set:
203
+ _dict['payee'] = None
204
+
205
+ # set to None if delivery_party (nullable) is None
206
+ # and model_fields_set contains the field
207
+ if self.delivery_party is None and "delivery_party" in self.model_fields_set:
208
+ _dict['delivery_party'] = None
209
+
210
+ # set to None if tax_representative (nullable) is None
211
+ # and model_fields_set contains the field
212
+ if self.tax_representative is None and "tax_representative" in self.model_fields_set:
213
+ _dict['tax_representative'] = None
214
+
215
+ # set to None if delivery_date (nullable) is None
216
+ # and model_fields_set contains the field
217
+ if self.delivery_date is None and "delivery_date" in self.model_fields_set:
218
+ _dict['delivery_date'] = None
219
+
220
+ # set to None if billing_period_start (nullable) is None
221
+ # and model_fields_set contains the field
222
+ if self.billing_period_start is None and "billing_period_start" in self.model_fields_set:
223
+ _dict['billing_period_start'] = None
224
+
225
+ # set to None if billing_period_end (nullable) is None
226
+ # and model_fields_set contains the field
227
+ if self.billing_period_end is None and "billing_period_end" in self.model_fields_set:
228
+ _dict['billing_period_end'] = None
229
+
230
+ # set to None if payment_reference (nullable) is None
231
+ # and model_fields_set contains the field
232
+ if self.payment_reference is None and "payment_reference" in self.model_fields_set:
233
+ _dict['payment_reference'] = None
234
+
235
+ # set to None if creditor_reference_id (nullable) is None
236
+ # and model_fields_set contains the field
237
+ if self.creditor_reference_id is None and "creditor_reference_id" in self.model_fields_set:
238
+ _dict['creditor_reference_id'] = None
239
+
240
+ # set to None if direct_debit_mandate_id (nullable) is None
241
+ # and model_fields_set contains the field
242
+ if self.direct_debit_mandate_id is None and "direct_debit_mandate_id" in self.model_fields_set:
243
+ _dict['direct_debit_mandate_id'] = None
244
+
245
+ # set to None if debtor_iban (nullable) is None
246
+ # and model_fields_set contains the field
247
+ if self.debtor_iban is None and "debtor_iban" in self.model_fields_set:
248
+ _dict['debtor_iban'] = None
249
+
250
+ # set to None if payment_terms (nullable) is None
251
+ # and model_fields_set contains the field
252
+ if self.payment_terms is None and "payment_terms" in self.model_fields_set:
253
+ _dict['payment_terms'] = None
254
+
255
+ # set to None if allowances_charges (nullable) is None
256
+ # and model_fields_set contains the field
257
+ if self.allowances_charges is None and "allowances_charges" in self.model_fields_set:
258
+ _dict['allowances_charges'] = None
259
+
260
+ # set to None if additional_documents (nullable) is None
261
+ # and model_fields_set contains the field
262
+ if self.additional_documents is None and "additional_documents" in self.model_fields_set:
263
+ _dict['additional_documents'] = None
264
+
265
+ # set to None if buyer_accounting_reference (nullable) is None
266
+ # and model_fields_set contains the field
267
+ if self.buyer_accounting_reference is None and "buyer_accounting_reference" in self.model_fields_set:
268
+ _dict['buyer_accounting_reference'] = None
269
+
270
+ # set to None if payment_card (nullable) is None
271
+ # and model_fields_set contains the field
272
+ if self.payment_card is None and "payment_card" in self.model_fields_set:
273
+ _dict['payment_card'] = None
274
+
275
+ return _dict
276
+
277
+ @classmethod
278
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
279
+ """Create an instance of FacturXInvoice from a dict"""
280
+ if obj is None:
281
+ return None
282
+
283
+ if not isinstance(obj, dict):
284
+ return cls.model_validate(obj)
285
+
286
+ _obj = cls.model_validate({
287
+ "invoice_number": obj.get("invoice_number"),
288
+ "payment_due_date": obj.get("payment_due_date"),
289
+ "invoice_date": obj.get("invoice_date"),
290
+ "submission_mode": obj.get("submission_mode"),
291
+ "recipient": Recipient.from_dict(obj["recipient"]) if obj.get("recipient") is not None else None,
292
+ "supplier": Supplier.from_dict(obj["supplier"]) if obj.get("supplier") is not None else None,
293
+ "invoicing_framework": InvoicingFramework.from_dict(obj["invoicing_framework"]) if obj.get("invoicing_framework") is not None else None,
294
+ "references": InvoiceReferences.from_dict(obj["references"]) if obj.get("references") is not None else None,
295
+ "totals": InvoiceTotals.from_dict(obj["totals"]) if obj.get("totals") is not None else None,
296
+ "invoice_lines": [InvoiceLine.from_dict(_item) for _item in obj["invoice_lines"]] if obj.get("invoice_lines") is not None else None,
297
+ "vat_lines": [VATLine.from_dict(_item) for _item in obj["vat_lines"]] if obj.get("vat_lines") is not None else None,
298
+ "notes": [InvoiceNote.from_dict(_item) for _item in obj["notes"]] if obj.get("notes") is not None else None,
299
+ "comment": obj.get("comment"),
300
+ "current_user_id": obj.get("current_user_id"),
301
+ "supplementary_attachments": [SupplementaryAttachment.from_dict(_item) for _item in obj["supplementary_attachments"]] if obj.get("supplementary_attachments") is not None else None,
302
+ "payee": Payee.from_dict(obj["payee"]) if obj.get("payee") is not None else None,
303
+ "delivery_party": DeliveryParty.from_dict(obj["delivery_party"]) if obj.get("delivery_party") is not None else None,
304
+ "tax_representative": TaxRepresentative.from_dict(obj["tax_representative"]) if obj.get("tax_representative") is not None else None,
305
+ "delivery_date": obj.get("delivery_date"),
306
+ "billing_period_start": obj.get("billing_period_start"),
307
+ "billing_period_end": obj.get("billing_period_end"),
308
+ "payment_reference": obj.get("payment_reference"),
309
+ "creditor_reference_id": obj.get("creditor_reference_id"),
310
+ "direct_debit_mandate_id": obj.get("direct_debit_mandate_id"),
311
+ "debtor_iban": obj.get("debtor_iban"),
312
+ "payment_terms": obj.get("payment_terms"),
313
+ "allowances_charges": [AllowanceCharge.from_dict(_item) for _item in obj["allowances_charges"]] if obj.get("allowances_charges") is not None else None,
314
+ "additional_documents": [AdditionalDocument.from_dict(_item) for _item in obj["additional_documents"]] if obj.get("additional_documents") is not None else None,
315
+ "buyer_accounting_reference": obj.get("buyer_accounting_reference"),
316
+ "payment_card": PaymentCard.from_dict(obj["payment_card"]) if obj.get("payment_card") is not None else None
317
+ })
318
+ return _obj
319
+
320
+
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ FactPulse REST API
5
+
6
+ REST API for electronic invoicing in France: Factur-X, AFNOR PDP/PA, electronic signatures. ## 🎯 Main Features ### 📄 Factur-X Invoice Generation - **Formats**: XML only or PDF/A-3 with embedded XML - **Profiles**: MINIMUM, BASIC, EN16931, EXTENDED - **Standards**: EN 16931 (EU directive 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Simplified Format**: Generation from SIRET + auto-enrichment (Chorus Pro API + Business Search) ### ✅ Validation and Compliance - **XML Validation**: Schematron (45 to 210+ rules depending on profile) - **PDF Validation**: PDF/A-3, Factur-X XMP metadata, electronic signatures - **VeraPDF**: Strict PDF/A validation (146+ ISO 19005-3 rules) - **Asynchronous Processing**: Celery support for heavy validations (VeraPDF) ### 📡 AFNOR PDP/PA Integration (XP Z12-013) - **Flow Submission**: Send invoices to Partner Dematerialization Platforms - **Flow Search**: View submitted invoices - **Download**: Retrieve PDF/A-3 with XML - **Directory Service**: Company search (SIREN/SIRET) - **Multi-client**: Support for multiple PDP configs per user (stored credentials or zero-storage) ### ✍️ PDF Electronic Signature - **Standards**: PAdES-B-B, PAdES-B-T (RFC 3161 timestamping), PAdES-B-LT (long-term archival) - **eIDAS Levels**: SES (self-signed), AdES (commercial CA), QES (QTSP) - **Validation**: Cryptographic integrity and certificate verification - **Certificate Generation**: Self-signed X.509 certificates for testing ### 🔄 Asynchronous Processing - **Celery**: Asynchronous generation, validation and signing - **Polling**: Status tracking via `/tasks/{task_id}/status` - **No timeout**: Ideal for large files or heavy validations ## 🔒 Authentication All requests require a **JWT token** in the Authorization header: ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### How to obtain a JWT token? #### 🔑 Method 1: `/api/token/` API (Recommended) **URL:** `https://www.factpulse.fr/api/token/` This method is **recommended** for integration in your applications and CI/CD workflows. **Prerequisites:** Having set a password on your account **For users registered via email/password:** - You already have a password, use it directly **For users registered via OAuth (Google/GitHub):** - You must first set a password at: https://www.factpulse.fr/accounts/password/set/ - Once the password is created, you can use the API **Request example:** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\" }' ``` **Optional `client_uid` parameter:** To select credentials for a specific client (PA/PDP, Chorus Pro, signing certificates), add `client_uid`: ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\", \"client_uid\": \"550e8400-e29b-41d4-a716-446655440000\" }' ``` The `client_uid` will be included in the JWT and allow the API to automatically use: - AFNOR/PDP credentials configured for this client - Chorus Pro credentials configured for this client - Electronic signature certificates configured for this client **Response:** ```json { \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\", // Access token (validity: 30 min) \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\" // Refresh token (validity: 7 days) } ``` **Advantages:** - ✅ Full automation (CI/CD, scripts) - ✅ Programmatic token management - ✅ Refresh token support for automatic access renewal - ✅ Easy integration in any language/tool #### 🖥️ Method 2: Dashboard Generation (Alternative) **URL:** https://www.factpulse.fr/dashboard/ This method is suitable for quick tests or occasional use via the graphical interface. **How it works:** - Log in to the dashboard - Use the \"Generate Test Token\" or \"Generate Production Token\" buttons - Works for **all** users (OAuth and email/password), without requiring a password **Token types:** - **Test Token**: 24h validity, 1000 calls/day quota (free) - **Production Token**: 7 days validity, quota based on your plan **Advantages:** - ✅ Quick for API testing - ✅ No password required - ✅ Simple visual interface **Disadvantages:** - ❌ Requires manual action - ❌ No refresh token - ❌ Less suited for automation ### 📚 Full Documentation For more information on authentication and API usage: https://www.factpulse.fr/documentation-api/
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import json
17
+ from enum import Enum
18
+ from typing_extensions import Self
19
+
20
+
21
+ class FacturXProfile(str, Enum):
22
+ """
23
+ Profil Factur-X pour la reponse API. Note: Simplifie par rapport a utils/facturx.FacturXProfile qui contient aussi les configurations XSLT. Celui-ci est pour l'API.
24
+ """
25
+
26
+ """
27
+ allowed enum values
28
+ """
29
+ MINIMUM = 'MINIMUM'
30
+ BASIC = 'BASIC'
31
+ EN16931 = 'EN16931'
32
+ EXTENDED = 'EXTENDED'
33
+
34
+ @classmethod
35
+ def from_json(cls, json_str: str) -> Self:
36
+ """Create an instance of FacturXProfile from a JSON string"""
37
+ return cls(json.loads(json_str))
38
+
39
+
@@ -0,0 +1,91 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ FactPulse REST API
5
+
6
+ REST API for electronic invoicing in France: Factur-X, AFNOR PDP/PA, electronic signatures. ## 🎯 Main Features ### 📄 Factur-X Invoice Generation - **Formats**: XML only or PDF/A-3 with embedded XML - **Profiles**: MINIMUM, BASIC, EN16931, EXTENDED - **Standards**: EN 16931 (EU directive 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Simplified Format**: Generation from SIRET + auto-enrichment (Chorus Pro API + Business Search) ### ✅ Validation and Compliance - **XML Validation**: Schematron (45 to 210+ rules depending on profile) - **PDF Validation**: PDF/A-3, Factur-X XMP metadata, electronic signatures - **VeraPDF**: Strict PDF/A validation (146+ ISO 19005-3 rules) - **Asynchronous Processing**: Celery support for heavy validations (VeraPDF) ### 📡 AFNOR PDP/PA Integration (XP Z12-013) - **Flow Submission**: Send invoices to Partner Dematerialization Platforms - **Flow Search**: View submitted invoices - **Download**: Retrieve PDF/A-3 with XML - **Directory Service**: Company search (SIREN/SIRET) - **Multi-client**: Support for multiple PDP configs per user (stored credentials or zero-storage) ### ✍️ PDF Electronic Signature - **Standards**: PAdES-B-B, PAdES-B-T (RFC 3161 timestamping), PAdES-B-LT (long-term archival) - **eIDAS Levels**: SES (self-signed), AdES (commercial CA), QES (QTSP) - **Validation**: Cryptographic integrity and certificate verification - **Certificate Generation**: Self-signed X.509 certificates for testing ### 🔄 Asynchronous Processing - **Celery**: Asynchronous generation, validation and signing - **Polling**: Status tracking via `/tasks/{task_id}/status` - **No timeout**: Ideal for large files or heavy validations ## 🔒 Authentication All requests require a **JWT token** in the Authorization header: ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### How to obtain a JWT token? #### 🔑 Method 1: `/api/token/` API (Recommended) **URL:** `https://www.factpulse.fr/api/token/` This method is **recommended** for integration in your applications and CI/CD workflows. **Prerequisites:** Having set a password on your account **For users registered via email/password:** - You already have a password, use it directly **For users registered via OAuth (Google/GitHub):** - You must first set a password at: https://www.factpulse.fr/accounts/password/set/ - Once the password is created, you can use the API **Request example:** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\" }' ``` **Optional `client_uid` parameter:** To select credentials for a specific client (PA/PDP, Chorus Pro, signing certificates), add `client_uid`: ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\", \"client_uid\": \"550e8400-e29b-41d4-a716-446655440000\" }' ``` The `client_uid` will be included in the JWT and allow the API to automatically use: - AFNOR/PDP credentials configured for this client - Chorus Pro credentials configured for this client - Electronic signature certificates configured for this client **Response:** ```json { \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\", // Access token (validity: 30 min) \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\" // Refresh token (validity: 7 days) } ``` **Advantages:** - ✅ Full automation (CI/CD, scripts) - ✅ Programmatic token management - ✅ Refresh token support for automatic access renewal - ✅ Easy integration in any language/tool #### 🖥️ Method 2: Dashboard Generation (Alternative) **URL:** https://www.factpulse.fr/dashboard/ This method is suitable for quick tests or occasional use via the graphical interface. **How it works:** - Log in to the dashboard - Use the \"Generate Test Token\" or \"Generate Production Token\" buttons - Works for **all** users (OAuth and email/password), without requiring a password **Token types:** - **Test Token**: 24h validity, 1000 calls/day quota (free) - **Production Token**: 7 days validity, quota based on your plan **Advantages:** - ✅ Quick for API testing - ✅ No password required - ✅ Simple visual interface **Disadvantages:** - ❌ Requires manual action - ❌ No refresh token - ❌ Less suited for automation ### 📚 Full Documentation For more information on authentication and API usage: https://www.factpulse.fr/documentation-api/
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from typing import Optional, Set
23
+ from typing_extensions import Self
24
+
25
+ class FacturXPDFInfo(BaseModel):
26
+ """
27
+ Information about the generated Factur-X PDF.
28
+ """ # noqa: E501
29
+ size: StrictInt = Field(description="PDF size in bytes")
30
+ profile: StrictStr = Field(description="Factur-X profile used")
31
+ signed: Optional[StrictBool] = Field(default=False, description="PDF electronically signed")
32
+ __properties: ClassVar[List[str]] = ["size", "profile", "signed"]
33
+
34
+ model_config = ConfigDict(
35
+ populate_by_name=True,
36
+ validate_assignment=True,
37
+ protected_namespaces=(),
38
+ )
39
+
40
+
41
+ def to_str(self) -> str:
42
+ """Returns the string representation of the model using alias"""
43
+ return pprint.pformat(self.model_dump(by_alias=True))
44
+
45
+ def to_json(self) -> str:
46
+ """Returns the JSON representation of the model using alias"""
47
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
48
+ return json.dumps(self.to_dict())
49
+
50
+ @classmethod
51
+ def from_json(cls, json_str: str) -> Optional[Self]:
52
+ """Create an instance of FacturXPDFInfo from a JSON string"""
53
+ return cls.from_dict(json.loads(json_str))
54
+
55
+ def to_dict(self) -> Dict[str, Any]:
56
+ """Return the dictionary representation of the model using alias.
57
+
58
+ This has the following differences from calling pydantic's
59
+ `self.model_dump(by_alias=True)`:
60
+
61
+ * `None` is only added to the output dict for nullable fields that
62
+ were set at model initialization. Other fields with value `None`
63
+ are ignored.
64
+ """
65
+ excluded_fields: Set[str] = set([
66
+ ])
67
+
68
+ _dict = self.model_dump(
69
+ by_alias=True,
70
+ exclude=excluded_fields,
71
+ exclude_none=True,
72
+ )
73
+ return _dict
74
+
75
+ @classmethod
76
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
77
+ """Create an instance of FacturXPDFInfo from a dict"""
78
+ if obj is None:
79
+ return None
80
+
81
+ if not isinstance(obj, dict):
82
+ return cls.model_validate(obj)
83
+
84
+ _obj = cls.model_validate({
85
+ "size": obj.get("size"),
86
+ "profile": obj.get("profile"),
87
+ "signed": obj.get("signed") if obj.get("signed") is not None else False
88
+ })
89
+ return _obj
90
+
91
+
@@ -0,0 +1,95 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ FactPulse REST API
5
+
6
+ REST API for electronic invoicing in France: Factur-X, AFNOR PDP/PA, electronic signatures. ## 🎯 Main Features ### 📄 Factur-X Invoice Generation - **Formats**: XML only or PDF/A-3 with embedded XML - **Profiles**: MINIMUM, BASIC, EN16931, EXTENDED - **Standards**: EN 16931 (EU directive 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Simplified Format**: Generation from SIRET + auto-enrichment (Chorus Pro API + Business Search) ### ✅ Validation and Compliance - **XML Validation**: Schematron (45 to 210+ rules depending on profile) - **PDF Validation**: PDF/A-3, Factur-X XMP metadata, electronic signatures - **VeraPDF**: Strict PDF/A validation (146+ ISO 19005-3 rules) - **Asynchronous Processing**: Celery support for heavy validations (VeraPDF) ### 📡 AFNOR PDP/PA Integration (XP Z12-013) - **Flow Submission**: Send invoices to Partner Dematerialization Platforms - **Flow Search**: View submitted invoices - **Download**: Retrieve PDF/A-3 with XML - **Directory Service**: Company search (SIREN/SIRET) - **Multi-client**: Support for multiple PDP configs per user (stored credentials or zero-storage) ### ✍️ PDF Electronic Signature - **Standards**: PAdES-B-B, PAdES-B-T (RFC 3161 timestamping), PAdES-B-LT (long-term archival) - **eIDAS Levels**: SES (self-signed), AdES (commercial CA), QES (QTSP) - **Validation**: Cryptographic integrity and certificate verification - **Certificate Generation**: Self-signed X.509 certificates for testing ### 🔄 Asynchronous Processing - **Celery**: Asynchronous generation, validation and signing - **Polling**: Status tracking via `/tasks/{task_id}/status` - **No timeout**: Ideal for large files or heavy validations ## 🔒 Authentication All requests require a **JWT token** in the Authorization header: ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### How to obtain a JWT token? #### 🔑 Method 1: `/api/token/` API (Recommended) **URL:** `https://www.factpulse.fr/api/token/` This method is **recommended** for integration in your applications and CI/CD workflows. **Prerequisites:** Having set a password on your account **For users registered via email/password:** - You already have a password, use it directly **For users registered via OAuth (Google/GitHub):** - You must first set a password at: https://www.factpulse.fr/accounts/password/set/ - Once the password is created, you can use the API **Request example:** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\" }' ``` **Optional `client_uid` parameter:** To select credentials for a specific client (PA/PDP, Chorus Pro, signing certificates), add `client_uid`: ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"your_email@example.com\", \"password\": \"your_password\", \"client_uid\": \"550e8400-e29b-41d4-a716-446655440000\" }' ``` The `client_uid` will be included in the JWT and allow the API to automatically use: - AFNOR/PDP credentials configured for this client - Chorus Pro credentials configured for this client - Electronic signature certificates configured for this client **Response:** ```json { \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\", // Access token (validity: 30 min) \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\" // Refresh token (validity: 7 days) } ``` **Advantages:** - ✅ Full automation (CI/CD, scripts) - ✅ Programmatic token management - ✅ Refresh token support for automatic access renewal - ✅ Easy integration in any language/tool #### 🖥️ Method 2: Dashboard Generation (Alternative) **URL:** https://www.factpulse.fr/dashboard/ This method is suitable for quick tests or occasional use via the graphical interface. **How it works:** - Log in to the dashboard - Use the \"Generate Test Token\" or \"Generate Production Token\" buttons - Works for **all** users (OAuth and email/password), without requiring a password **Token types:** - **Test Token**: 24h validity, 1000 calls/day quota (free) - **Production Token**: 7 days validity, quota based on your plan **Advantages:** - ✅ Quick for API testing - ✅ No password required - ✅ Simple visual interface **Disadvantages:** - ❌ Requires manual action - ❌ No refresh token - ❌ Less suited for automation ### 📚 Full Documentation For more information on authentication and API usage: https://www.factpulse.fr/documentation-api/
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from typing import Optional, Set
23
+ from typing_extensions import Self
24
+
25
+ class FactureElectroniqueRestApiSchemasChorusProChorusProCredentials(BaseModel):
26
+ """
27
+ Chorus Pro credentials for Zero-Trust mode. **Zero-Trust Mode**: Credentials are passed in each request and are NEVER stored. **Security**: - Credentials are never persisted in the database - They are used only for the duration of the request - Secure transmission via HTTPS **Use cases**: - High-security environments (banks, administrations) - Strict GDPR compliance - Tests with temporary credentials - Users who don't want to store their credentials
28
+ """ # noqa: E501
29
+ piste_client_id: StrictStr = Field(description="PISTE Client ID (government API portal)", alias="pisteClientId")
30
+ piste_client_secret: StrictStr = Field(description="PISTE Client Secret", alias="pisteClientSecret")
31
+ chorus_pro_login: StrictStr = Field(description="Chorus Pro login", alias="chorusProLogin")
32
+ chorus_pro_password: StrictStr = Field(description="Chorus Pro password", alias="chorusProPassword")
33
+ sandbox: Optional[StrictBool] = Field(default=True, description="Use sandbox environment (true) or production (false)")
34
+ __properties: ClassVar[List[str]] = ["pisteClientId", "pisteClientSecret", "chorusProLogin", "chorusProPassword", "sandbox"]
35
+
36
+ model_config = ConfigDict(
37
+ populate_by_name=True,
38
+ validate_assignment=True,
39
+ protected_namespaces=(),
40
+ )
41
+
42
+
43
+ def to_str(self) -> str:
44
+ """Returns the string representation of the model using alias"""
45
+ return pprint.pformat(self.model_dump(by_alias=True))
46
+
47
+ def to_json(self) -> str:
48
+ """Returns the JSON representation of the model using alias"""
49
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
50
+ return json.dumps(self.to_dict())
51
+
52
+ @classmethod
53
+ def from_json(cls, json_str: str) -> Optional[Self]:
54
+ """Create an instance of FactureElectroniqueRestApiSchemasChorusProChorusProCredentials from a JSON string"""
55
+ return cls.from_dict(json.loads(json_str))
56
+
57
+ def to_dict(self) -> Dict[str, Any]:
58
+ """Return the dictionary representation of the model using alias.
59
+
60
+ This has the following differences from calling pydantic's
61
+ `self.model_dump(by_alias=True)`:
62
+
63
+ * `None` is only added to the output dict for nullable fields that
64
+ were set at model initialization. Other fields with value `None`
65
+ are ignored.
66
+ """
67
+ excluded_fields: Set[str] = set([
68
+ ])
69
+
70
+ _dict = self.model_dump(
71
+ by_alias=True,
72
+ exclude=excluded_fields,
73
+ exclude_none=True,
74
+ )
75
+ return _dict
76
+
77
+ @classmethod
78
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
79
+ """Create an instance of FactureElectroniqueRestApiSchemasChorusProChorusProCredentials from a dict"""
80
+ if obj is None:
81
+ return None
82
+
83
+ if not isinstance(obj, dict):
84
+ return cls.model_validate(obj)
85
+
86
+ _obj = cls.model_validate({
87
+ "pisteClientId": obj.get("pisteClientId"),
88
+ "pisteClientSecret": obj.get("pisteClientSecret"),
89
+ "chorusProLogin": obj.get("chorusProLogin"),
90
+ "chorusProPassword": obj.get("chorusProPassword"),
91
+ "sandbox": obj.get("sandbox") if obj.get("sandbox") is not None else True
92
+ })
93
+ return _obj
94
+
95
+