pennylane-sdk 0.1.0__tar.gz

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.
Files changed (190) hide show
  1. pennylane_sdk-0.1.0/.gitattributes +3 -0
  2. pennylane_sdk-0.1.0/.github/workflows/ci.yml +68 -0
  3. pennylane_sdk-0.1.0/.github/workflows/docs.yml +37 -0
  4. pennylane_sdk-0.1.0/.github/workflows/release.yml +39 -0
  5. pennylane_sdk-0.1.0/.gitignore +31 -0
  6. pennylane_sdk-0.1.0/CHANGELOG.md +24 -0
  7. pennylane_sdk-0.1.0/CONTRIBUTING.md +70 -0
  8. pennylane_sdk-0.1.0/LICENSE +21 -0
  9. pennylane_sdk-0.1.0/PKG-INFO +140 -0
  10. pennylane_sdk-0.1.0/README.fr.md +128 -0
  11. pennylane_sdk-0.1.0/README.md +107 -0
  12. pennylane_sdk-0.1.0/SECURITY.md +18 -0
  13. pennylane_sdk-0.1.0/docs/api/clients.md +13 -0
  14. pennylane_sdk-0.1.0/docs/api/company/accounting.md +17 -0
  15. pennylane_sdk-0.1.0/docs/api/company/analytics.md +7 -0
  16. pennylane_sdk-0.1.0/docs/api/company/banking.md +9 -0
  17. pennylane_sdk-0.1.0/docs/api/company/e-invoicing.md +7 -0
  18. pennylane_sdk-0.1.0/docs/api/company/exports.md +11 -0
  19. pennylane_sdk-0.1.0/docs/api/company/invoicing.md +24 -0
  20. pennylane_sdk-0.1.0/docs/api/company/mandates.md +9 -0
  21. pennylane_sdk-0.1.0/docs/api/company/misc.md +11 -0
  22. pennylane_sdk-0.1.0/docs/api/company/purchases.md +9 -0
  23. pennylane_sdk-0.1.0/docs/api/errors.md +27 -0
  24. pennylane_sdk-0.1.0/docs/api/filters.md +5 -0
  25. pennylane_sdk-0.1.0/docs/api/firm.md +49 -0
  26. pennylane_sdk-0.1.0/docs/api/oauth.md +5 -0
  27. pennylane_sdk-0.1.0/docs/api/pagination.md +11 -0
  28. pennylane_sdk-0.1.0/docs/api/webhooks.md +5 -0
  29. pennylane_sdk-0.1.0/docs/changelog.md +3 -0
  30. pennylane_sdk-0.1.0/docs/contributing.md +3 -0
  31. pennylane_sdk-0.1.0/docs/design/resource-map.md +97 -0
  32. pennylane_sdk-0.1.0/docs/getting-started.md +104 -0
  33. pennylane_sdk-0.1.0/docs/guides/accounting.md +112 -0
  34. pennylane_sdk-0.1.0/docs/guides/authentication.md +57 -0
  35. pennylane_sdk-0.1.0/docs/guides/e-invoicing.md +58 -0
  36. pennylane_sdk-0.1.0/docs/guides/errors-and-retries.md +77 -0
  37. pennylane_sdk-0.1.0/docs/guides/firm-api.md +84 -0
  38. pennylane_sdk-0.1.0/docs/guides/invoicing.md +129 -0
  39. pennylane_sdk-0.1.0/docs/guides/oauth.md +51 -0
  40. pennylane_sdk-0.1.0/docs/guides/pagination.md +88 -0
  41. pennylane_sdk-0.1.0/docs/guides/webhooks.md +64 -0
  42. pennylane_sdk-0.1.0/docs/index.md +77 -0
  43. pennylane_sdk-0.1.0/examples/bulk_read_async.py +35 -0
  44. pennylane_sdk-0.1.0/examples/einvoice_import.py +20 -0
  45. pennylane_sdk-0.1.0/examples/firm_portfolio.py +22 -0
  46. pennylane_sdk-0.1.0/examples/invoicing_lifecycle.py +55 -0
  47. pennylane_sdk-0.1.0/examples/quickstart.py +23 -0
  48. pennylane_sdk-0.1.0/examples/webhook_receiver.py +41 -0
  49. pennylane_sdk-0.1.0/mkdocs.yml +95 -0
  50. pennylane_sdk-0.1.0/pyproject.toml +101 -0
  51. pennylane_sdk-0.1.0/scripts/check_coverage.py +170 -0
  52. pennylane_sdk-0.1.0/scripts/show_endpoint.py +151 -0
  53. pennylane_sdk-0.1.0/scripts/update_specs.py +47 -0
  54. pennylane_sdk-0.1.0/specs/company_v2.json +127856 -0
  55. pennylane_sdk-0.1.0/specs/firm_v1.json +31255 -0
  56. pennylane_sdk-0.1.0/src/pennylane_sdk/__init__.py +70 -0
  57. pennylane_sdk-0.1.0/src/pennylane_sdk/_base_client.py +568 -0
  58. pennylane_sdk-0.1.0/src/pennylane_sdk/_client.py +511 -0
  59. pennylane_sdk-0.1.0/src/pennylane_sdk/_exceptions.py +232 -0
  60. pennylane_sdk-0.1.0/src/pennylane_sdk/_files.py +69 -0
  61. pennylane_sdk-0.1.0/src/pennylane_sdk/_models.py +75 -0
  62. pennylane_sdk-0.1.0/src/pennylane_sdk/_pagination.py +258 -0
  63. pennylane_sdk-0.1.0/src/pennylane_sdk/_resource.py +295 -0
  64. pennylane_sdk-0.1.0/src/pennylane_sdk/_throttle.py +75 -0
  65. pennylane_sdk-0.1.0/src/pennylane_sdk/_version.py +1 -0
  66. pennylane_sdk-0.1.0/src/pennylane_sdk/filters.py +137 -0
  67. pennylane_sdk-0.1.0/src/pennylane_sdk/oauth.py +251 -0
  68. pennylane_sdk-0.1.0/src/pennylane_sdk/py.typed +0 -0
  69. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/__init__.py +0 -0
  70. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/__init__.py +139 -0
  71. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/accounting.py +128 -0
  72. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/bank_accounts.py +194 -0
  73. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/billing_subscriptions.py +355 -0
  74. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/categories.py +293 -0
  75. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/changelogs.py +350 -0
  76. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/commercial_documents.py +244 -0
  77. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/customer_invoice_templates.py +61 -0
  78. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/customer_invoices.py +1154 -0
  79. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/customers.py +643 -0
  80. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/e_invoices.py +97 -0
  81. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/exports.py +243 -0
  82. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/file_attachments.py +69 -0
  83. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/journals.py +104 -0
  84. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/ledger_accounts.py +175 -0
  85. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/ledger_entries.py +335 -0
  86. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/ledger_entry_lines.py +305 -0
  87. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/mandates.py +591 -0
  88. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/me.py +35 -0
  89. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/products.py +227 -0
  90. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/purchase_requests.py +186 -0
  91. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/quotes.py +481 -0
  92. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/supplier_invoices.py +728 -0
  93. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/suppliers.py +310 -0
  94. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/transactions.py +299 -0
  95. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/company/webhook_subscriptions.py +226 -0
  96. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/__init__.py +109 -0
  97. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/accounting.py +809 -0
  98. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/banking.py +308 -0
  99. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/categories.py +207 -0
  100. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/changelogs.py +206 -0
  101. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/companies.py +78 -0
  102. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/dms.py +285 -0
  103. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/exports.py +189 -0
  104. pennylane_sdk-0.1.0/src/pennylane_sdk/resources/firm/invoicing.py +308 -0
  105. pennylane_sdk-0.1.0/src/pennylane_sdk/types/__init__.py +0 -0
  106. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/__init__.py +302 -0
  107. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/accounting.py +36 -0
  108. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/bank_accounts.py +64 -0
  109. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/billing_subscriptions.py +177 -0
  110. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/categories.py +49 -0
  111. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/changelogs.py +22 -0
  112. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/commercial_documents.py +142 -0
  113. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/customer_invoice_templates.py +21 -0
  114. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/customer_invoices.py +326 -0
  115. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/customers.py +112 -0
  116. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/e_invoices.py +36 -0
  117. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/exports.py +48 -0
  118. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/file_attachments.py +22 -0
  119. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/journals.py +19 -0
  120. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/ledger_accounts.py +27 -0
  121. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/ledger_entries.py +111 -0
  122. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/ledger_entry_lines.py +102 -0
  123. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/mandates.py +149 -0
  124. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/me.py +39 -0
  125. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/products.py +37 -0
  126. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/purchase_requests.py +78 -0
  127. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/quotes.py +134 -0
  128. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/supplier_invoices.py +255 -0
  129. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/suppliers.py +74 -0
  130. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/transactions.py +152 -0
  131. pennylane_sdk-0.1.0/src/pennylane_sdk/types/company/webhook_subscriptions.py +38 -0
  132. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/__init__.py +134 -0
  133. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/accounting.py +182 -0
  134. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/banking.py +147 -0
  135. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/categories.py +55 -0
  136. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/changelogs.py +22 -0
  137. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/companies.py +26 -0
  138. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/dms.py +64 -0
  139. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/exports.py +35 -0
  140. pennylane_sdk-0.1.0/src/pennylane_sdk/types/firm/invoicing.py +300 -0
  141. pennylane_sdk-0.1.0/src/pennylane_sdk/webhooks.py +127 -0
  142. pennylane_sdk-0.1.0/tests/__init__.py +0 -0
  143. pennylane_sdk-0.1.0/tests/company/__init__.py +0 -0
  144. pennylane_sdk-0.1.0/tests/company/test_accounting.py +96 -0
  145. pennylane_sdk-0.1.0/tests/company/test_bank_accounts.py +131 -0
  146. pennylane_sdk-0.1.0/tests/company/test_billing_subscriptions.py +273 -0
  147. pennylane_sdk-0.1.0/tests/company/test_categories.py +195 -0
  148. pennylane_sdk-0.1.0/tests/company/test_changelogs.py +63 -0
  149. pennylane_sdk-0.1.0/tests/company/test_commercial_documents.py +220 -0
  150. pennylane_sdk-0.1.0/tests/company/test_customer_invoice_templates.py +47 -0
  151. pennylane_sdk-0.1.0/tests/company/test_customer_invoices.py +729 -0
  152. pennylane_sdk-0.1.0/tests/company/test_customers.py +360 -0
  153. pennylane_sdk-0.1.0/tests/company/test_e_invoices.py +87 -0
  154. pennylane_sdk-0.1.0/tests/company/test_exports.py +195 -0
  155. pennylane_sdk-0.1.0/tests/company/test_file_attachments.py +65 -0
  156. pennylane_sdk-0.1.0/tests/company/test_journals.py +78 -0
  157. pennylane_sdk-0.1.0/tests/company/test_ledger_accounts.py +98 -0
  158. pennylane_sdk-0.1.0/tests/company/test_ledger_entries.py +201 -0
  159. pennylane_sdk-0.1.0/tests/company/test_ledger_entry_lines.py +243 -0
  160. pennylane_sdk-0.1.0/tests/company/test_mandates.py +393 -0
  161. pennylane_sdk-0.1.0/tests/company/test_me.py +49 -0
  162. pennylane_sdk-0.1.0/tests/company/test_products.py +118 -0
  163. pennylane_sdk-0.1.0/tests/company/test_purchase_requests.py +185 -0
  164. pennylane_sdk-0.1.0/tests/company/test_quotes.py +289 -0
  165. pennylane_sdk-0.1.0/tests/company/test_supplier_invoices.py +501 -0
  166. pennylane_sdk-0.1.0/tests/company/test_suppliers.py +184 -0
  167. pennylane_sdk-0.1.0/tests/company/test_transactions.py +202 -0
  168. pennylane_sdk-0.1.0/tests/company/test_webhook_subscriptions.py +132 -0
  169. pennylane_sdk-0.1.0/tests/conftest.py +35 -0
  170. pennylane_sdk-0.1.0/tests/firm/__init__.py +0 -0
  171. pennylane_sdk-0.1.0/tests/firm/test_accounting.py +393 -0
  172. pennylane_sdk-0.1.0/tests/firm/test_banking.py +169 -0
  173. pennylane_sdk-0.1.0/tests/firm/test_categories.py +148 -0
  174. pennylane_sdk-0.1.0/tests/firm/test_changelogs.py +100 -0
  175. pennylane_sdk-0.1.0/tests/firm/test_companies.py +87 -0
  176. pennylane_sdk-0.1.0/tests/firm/test_dms.py +166 -0
  177. pennylane_sdk-0.1.0/tests/firm/test_exports.py +148 -0
  178. pennylane_sdk-0.1.0/tests/firm/test_invoicing.py +251 -0
  179. pennylane_sdk-0.1.0/tests/test_base_client.py +241 -0
  180. pennylane_sdk-0.1.0/tests/test_client.py +68 -0
  181. pennylane_sdk-0.1.0/tests/test_exceptions.py +111 -0
  182. pennylane_sdk-0.1.0/tests/test_files.py +60 -0
  183. pennylane_sdk-0.1.0/tests/test_filters.py +72 -0
  184. pennylane_sdk-0.1.0/tests/test_models.py +69 -0
  185. pennylane_sdk-0.1.0/tests/test_oauth.py +93 -0
  186. pennylane_sdk-0.1.0/tests/test_pagination.py +182 -0
  187. pennylane_sdk-0.1.0/tests/test_review_fixes.py +195 -0
  188. pennylane_sdk-0.1.0/tests/test_throttle.py +59 -0
  189. pennylane_sdk-0.1.0/tests/test_webhooks.py +82 -0
  190. pennylane_sdk-0.1.0/uv.lock +1339 -0
@@ -0,0 +1,3 @@
1
+ * text=auto eol=lf
2
+ *.png binary
3
+ *.jpg binary
@@ -0,0 +1,68 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ lint:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v5
18
+ - run: uv sync --frozen
19
+ - name: Ruff
20
+ run: uv run ruff check src tests scripts
21
+ - name: Mypy (strict)
22
+ run: uv run mypy --strict src
23
+
24
+ coverage-audit:
25
+ name: API coverage audit (213 operations)
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ - uses: astral-sh/setup-uv@v5
30
+ - name: Every spec operation implemented (sync + async)
31
+ run: uv run python scripts/check_coverage.py
32
+
33
+ test:
34
+ runs-on: ${{ matrix.os }}
35
+ strategy:
36
+ fail-fast: false
37
+ matrix:
38
+ os: [ubuntu-latest, windows-latest]
39
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - uses: astral-sh/setup-uv@v5
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+ - run: uv sync --frozen
46
+ - name: Tests
47
+ run: uv run pytest -q
48
+
49
+ docs:
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ - uses: astral-sh/setup-uv@v5
54
+ - run: uv sync --frozen
55
+ - name: Build docs (strict)
56
+ run: uv run mkdocs build --strict
57
+
58
+ build:
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+ - uses: astral-sh/setup-uv@v5
63
+ - name: Build sdist and wheel
64
+ run: uv build
65
+ - uses: actions/upload-artifact@v4
66
+ with:
67
+ name: dist
68
+ path: dist/
@@ -0,0 +1,37 @@
1
+ name: Deploy docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: read
9
+ pages: write
10
+ id-token: write
11
+
12
+ concurrency:
13
+ group: pages
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ build:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: astral-sh/setup-uv@v5
22
+ - run: uv sync --frozen
23
+ - name: Build site
24
+ run: uv run mkdocs build --strict
25
+ - uses: actions/upload-pages-artifact@v3
26
+ with:
27
+ path: site/
28
+
29
+ deploy:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment:
33
+ name: github-pages
34
+ url: ${{ steps.deployment.outputs.page_url }}
35
+ steps:
36
+ - id: deployment
37
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,39 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: astral-sh/setup-uv@v5
13
+ - run: uv sync --frozen
14
+ - name: Run tests
15
+ run: uv run pytest -q
16
+ - name: Coverage audit
17
+ run: uv run python scripts/check_coverage.py
18
+ - name: Build sdist and wheel
19
+ run: uv build
20
+ - uses: actions/upload-artifact@v4
21
+ with:
22
+ name: dist
23
+ path: dist/
24
+
25
+ publish:
26
+ needs: build
27
+ runs-on: ubuntu-latest
28
+ environment:
29
+ name: pypi
30
+ url: https://pypi.org/project/pennylane-sdk/
31
+ permissions:
32
+ id-token: write # OIDC trusted publishing — no API token needed
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+ - name: Publish to PyPI
39
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ venv/
9
+
10
+ # Tooling caches
11
+ .pytest_cache/
12
+ .mypy_cache/
13
+ .ruff_cache/
14
+ .coverage
15
+ coverage.xml
16
+ htmlcov/
17
+
18
+ # Docs build
19
+ site/
20
+
21
+ # IDE / OS
22
+ .idea/
23
+ .vscode/
24
+ .DS_Store
25
+
26
+ # Local secrets (never commit API tokens)
27
+ .env
28
+ .env.*
29
+
30
+ # Local tooling configuration
31
+ .claude/
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/).
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.1.0] - 2026-07-08
8
+
9
+ Initial release.
10
+
11
+ ### Added
12
+
13
+ - Full coverage of the Pennylane **Company API v2**: 165 operations across 24 resource modules (customer and supplier invoicing, quotes, customers, products, billing subscriptions, banking, ledger, lettering, trial balance, analytics, FEC/GL/AGL exports, SEPA/GoCardless/Pro Account mandates, e-invoicing, changelogs, webhook subscriptions).
14
+ - Full coverage of the Pennylane **Firm API v1**: 48 operations (companies portfolio, accounting, DMS, exports, invoicing, banking, categories, changelogs).
15
+ - Sync (`Pennylane`, `PennylaneFirm`) and async (`AsyncPennylane`, `AsyncPennylaneFirm`) clients with identical surfaces.
16
+ - Typed Pydantic response models; monetary values as `Decimal` serialized to API-compliant strings.
17
+ - Auto-paginating cursor and page-number pages, re-sending filters across pages.
18
+ - Client-side throttling to the official rate limits, on by default.
19
+ - Conservative retry policy safe for a non-idempotent accounting API (POST never retried on 5xx).
20
+ - Defensive error parsing with a full exception hierarchy.
21
+ - Typed filter builders (`pennylane_sdk.filters`).
22
+ - OAuth 2.0 helpers with serialized refresh (Refresh Token Rotation safe).
23
+ - Webhook signature verification (constant-time HMAC) and payload parsing.
24
+ - Coverage audit script validating the SDK against the vendored official OpenAPI specs.
@@ -0,0 +1,70 @@
1
+ # Contributing
2
+
3
+ Thanks for helping make pennylane-sdk better! Contributions of every size are welcome: bug reports, docs fixes, new endpoint coverage, ideas.
4
+
5
+ ## Development setup
6
+
7
+ Requirements: Python 3.10+ and [uv](https://docs.astral.sh/uv/).
8
+
9
+ ```bash
10
+ git clone https://github.com/GoatAndCow7/pennylane-sdk
11
+ cd pennylane-sdk
12
+ uv sync
13
+ ```
14
+
15
+ Run the checks the CI runs:
16
+
17
+ ```bash
18
+ uv run pytest # tests (all mocked, no token needed)
19
+ uv run mypy --strict src # type checking
20
+ uv run ruff check src tests scripts # lint
21
+ uv run python scripts/check_coverage.py # every API operation implemented?
22
+ uv run mkdocs serve # docs live preview
23
+ ```
24
+
25
+ ## Project layout
26
+
27
+ ```
28
+ specs/ vendored official OpenAPI specs (source of truth)
29
+ scripts/update_specs.py refresh the specs from pennylane.readme.io
30
+ scripts/check_coverage.py audits that every spec operation exists in sync + async
31
+ scripts/show_endpoint.py inspect one endpoint's schema from the specs
32
+ src/pennylane_sdk/
33
+ _base_client.py HTTP engine: auth, retries, throttle, errors
34
+ _pagination.py cursor and page-number auto-paginating pages
35
+ resources/company|firm/ one module per URL namespace, sync + Async classes
36
+ types/company|firm/ Pydantic response models
37
+ tests/ mirrors resources/, respx-mocked
38
+ docs/ mkdocs-material site
39
+ ```
40
+
41
+ ## Adding or fixing an endpoint
42
+
43
+ 1. Find the operation in the spec: `uv run python scripts/show_endpoint.py company "customer_invoices/{id}/finalize" put`
44
+ 2. Follow the conventions in `docs/design/resource-map.md` (method naming, models, docstrings). `src/pennylane_sdk/resources/company/products.py` is the reference style.
45
+ 3. Write the resource method (sync and async), the models, and tests.
46
+ 4. Make the four checks above pass. `check_coverage.py` must report full coverage.
47
+
48
+ ## Style rules
49
+
50
+ - English everywhere in code and docs.
51
+ - No em dashes or en dashes in text; use plain punctuation.
52
+ - Docstrings state the required scope and link the official reference page.
53
+ - Response model fields are optional (`| None = None`) except `id`; monetary strings use the `Money` type.
54
+
55
+ ## Releasing (maintainers)
56
+
57
+ 1. Update `CHANGELOG.md` and bump the version in `pyproject.toml` and `src/pennylane_sdk/_version.py`.
58
+ 2. Tag: `git tag v0.x.y && git push --tags`.
59
+ 3. The `release.yml` workflow tests, builds and publishes to PyPI via trusted publishing.
60
+
61
+ ## When the API changes
62
+
63
+ Refresh the vendored specs and see what the coverage audit says:
64
+
65
+ ```bash
66
+ uv run python scripts/update_specs.py
67
+ uv run python scripts/check_coverage.py
68
+ ```
69
+
70
+ New operations show up as MISSING; removed ones as UNKNOWN CALL. Please open an issue even if you cannot fix it yourself.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pennylane SDK Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: pennylane-sdk
3
+ Version: 0.1.0
4
+ Summary: Unofficial Python SDK for the Pennylane API — the French accounting and invoicing platform
5
+ Project-URL: Homepage, https://github.com/pennylane-sdk/pennylane-sdk
6
+ Project-URL: Documentation, https://github.com/pennylane-sdk/pennylane-sdk#readme
7
+ Project-URL: Repository, https://github.com/pennylane-sdk/pennylane-sdk
8
+ Project-URL: Changelog, https://github.com/pennylane-sdk/pennylane-sdk/blob/main/CHANGELOG.md
9
+ Author: Pennylane SDK Contributors
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: accounting,api,comptabilite,e-invoicing,factur-x,facturation,france,invoicing,pennylane,sdk
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Natural Language :: English
16
+ Classifier: Natural Language :: French
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: anyio<5,>=4.0
29
+ Requires-Dist: httpx<1,>=0.27
30
+ Requires-Dist: pydantic<3,>=2.7
31
+ Requires-Dist: typing-extensions>=4.10
32
+ Description-Content-Type: text/markdown
33
+
34
+ # pennylane-sdk
35
+
36
+ > The unofficial Python SDK for the [Pennylane](https://www.pennylane.com) API, the French accounting and invoicing platform.
37
+
38
+ 🇫🇷 [Version française](README.fr.md)
39
+
40
+ [![CI](https://github.com/GoatAndCow7/pennylane-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/GoatAndCow7/pennylane-sdk/actions/workflows/ci.yml)
41
+ [![PyPI](https://img.shields.io/pypi/v/pennylane-sdk)](https://pypi.org/project/pennylane-sdk/)
42
+ [![Python](https://img.shields.io/pypi/pyversions/pennylane-sdk)](https://pypi.org/project/pennylane-sdk/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-teal.svg)](LICENSE)
44
+
45
+ **[Documentation](https://goatandcow7.github.io/pennylane-sdk/)** | [API coverage: 213/213 operations](#complete-api-coverage)
46
+
47
+ - **Complete**: every operation of the Company API v2 (165) and the Firm API v1 (48), in sync and async, audited against the official OpenAPI specs in CI.
48
+ - **Typed**: Pydantic models everywhere; monetary amounts are `Decimal`, never floats.
49
+ - **Safe for accounting**: the API has no idempotency, so POST is never retried after a server error. No duplicate invoices from a network hiccup.
50
+ - **Rate-limit proof**: built-in client-side throttling to the official limits, plus `retry-after` aware retries on 429.
51
+ - **Effortless pagination**: iterate a list call, the SDK fetches the pages.
52
+
53
+ > Not affiliated with Pennylane SAS. Unrelated to the PennyLane quantum computing framework (which owns `pennylane` on PyPI; this package is `pennylane-sdk`).
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install pennylane-sdk
59
+ ```
60
+
61
+ Python 3.10+.
62
+
63
+ ## Quickstart
64
+
65
+ Create an API token in Pennylane (**Settings > Connectivity > Developers**), then:
66
+
67
+ ```python
68
+ from pennylane_sdk import Pennylane, filters
69
+
70
+ client = Pennylane() # reads PENNYLANE_API_TOKEN
71
+
72
+ # List and filter, with transparent pagination
73
+ for invoice in client.customer_invoices.list(
74
+ filter=[filters.gte("date", "2026-01-01")],
75
+ sort="-date",
76
+ ):
77
+ print(invoice.invoice_number, invoice.currency_amount)
78
+
79
+ # Create, finalize, send
80
+ invoice = client.customer_invoices.create(
81
+ customer_id=123,
82
+ date="2026-07-08",
83
+ deadline="2026-08-07",
84
+ invoice_lines=[{"product_id": 45, "quantity": "2"}],
85
+ )
86
+ client.customer_invoices.finalize(invoice.id)
87
+ client.customer_invoices.send_by_email(invoice.id)
88
+ ```
89
+
90
+ Async, same surface:
91
+
92
+ ```python
93
+ from pennylane_sdk import AsyncPennylane
94
+
95
+ async with AsyncPennylane() as client:
96
+ page = await client.customer_invoices.list(limit=100)
97
+ async for invoice in page:
98
+ ...
99
+ ```
100
+
101
+ Accounting firms, across the whole portfolio:
102
+
103
+ ```python
104
+ from pennylane_sdk import PennylaneFirm
105
+
106
+ firm = PennylaneFirm() # reads PENNYLANE_FIRM_API_TOKEN
107
+ for company in firm.companies.list():
108
+ for row in firm.trial_balance.list(
109
+ company.id, period_start="2026-01-01", period_end="2026-06-30"
110
+ ):
111
+ ...
112
+ ```
113
+
114
+ French e-invoicing (2026 reform), Pennylane being an accredited Plateforme Agréée:
115
+
116
+ ```python
117
+ client.customer_invoices.send_to_pa(invoice.id) # emit through the PA
118
+ client.supplier_invoices.import_e_invoice(file="factur-x.pdf") # ingest Factur-X/UBL/CII
119
+ ```
120
+
121
+ ## Complete API coverage
122
+
123
+ | API | Operations | Resources |
124
+ |---|---|---|
125
+ | Company v2 | 165/165 | customer and supplier invoices, quotes, customers, products, billing subscriptions, banking and reconciliation, journals, ledger entries, lettering, trial balance, analytics, FEC/GL/AGL exports, SEPA/GoCardless/Pro mandates, e-invoicing, changelogs, webhooks |
126
+ | Firm v1 | 48/48 | client portfolio, accounting, DMS, exports, invoicing (read), banking, analytics, changelogs |
127
+
128
+ Coverage is not a promise: `scripts/check_coverage.py` verifies in CI that every operation in the vendored official OpenAPI specs exists in both the sync and async clients.
129
+
130
+ ## Learn more
131
+
132
+ - [Getting started](https://goatandcow7.github.io/pennylane-sdk/getting-started/)
133
+ - [Guides](https://goatandcow7.github.io/pennylane-sdk/guides/authentication/): authentication, pagination and filtering, errors and retries, invoicing lifecycle, e-invoicing 2026, accounting, Firm API, webhooks, OAuth apps
134
+ - [API reference](https://goatandcow7.github.io/pennylane-sdk/api/clients/)
135
+ - [Examples](examples/)
136
+ - [Contributing](CONTRIBUTING.md)
137
+
138
+ ## License
139
+
140
+ [MIT](LICENSE). Build whatever you want with it.
@@ -0,0 +1,128 @@
1
+ # pennylane-sdk
2
+
3
+ > Le SDK Python non officiel pour l'API de [Pennylane](https://www.pennylane.com), la plateforme française de comptabilité et de facturation.
4
+
5
+ 🇬🇧 [English version](README.md)
6
+
7
+ **[Documentation complète](https://goatandcow7.github.io/pennylane-sdk/)** (en anglais)
8
+
9
+ ## Pourquoi ce SDK
10
+
11
+ - **Complet** : la totalité des opérations de l'API Entreprise v2 (165) et de l'API Cabinet v1 (48), en synchrone et en asynchrone. La couverture est vérifiée automatiquement en CI contre les spécifications OpenAPI officielles de Pennylane.
12
+ - **Typé** : chaque réponse est un modèle Pydantic. Les montants sont des `Decimal`, jamais des floats, exactement comme l'API le demande (les montants circulent en chaînes pour éviter les erreurs d'arrondi).
13
+ - **Sûr pour la compta** : l'API Pennylane n'a pas d'idempotence côté serveur. Le SDK ne réessaie donc jamais un POST après une erreur serveur : impossible de créer une facture en double à cause d'un souci réseau.
14
+ - **Anti rate-limit** : les requêtes sont cadencées côté client aux limites officielles (25 requêtes / 5 s pour les entreprises, 5/s pour les cabinets), et les 429 sont réessayés en respectant `retry-after`. Vos exports de masse passent sans effort.
15
+ - **Pagination invisible** : itérez sur un `list()` et le SDK va chercher les pages suivantes tout seul, en renvoyant vos filtres comme l'API l'exige.
16
+
17
+ > Projet communautaire, non affilié à Pennylane SAS. Sans rapport avec le framework de calcul quantique PennyLane (qui possède le nom `pennylane` sur PyPI ; ce paquet s'appelle `pennylane-sdk`).
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install pennylane-sdk
23
+ ```
24
+
25
+ Python 3.10 ou plus récent.
26
+
27
+ ## Démarrage rapide
28
+
29
+ Créez un jeton API dans Pennylane (**Paramètres > Connectivité > Développeurs**), copiez-le immédiatement (il n'est affiché qu'une fois), puis :
30
+
31
+ ```bash
32
+ export PENNYLANE_API_TOKEN="votre-jeton"
33
+ ```
34
+
35
+ ```python
36
+ from pennylane_sdk import Pennylane, filters
37
+
38
+ client = Pennylane()
39
+
40
+ # Lister et filtrer, pagination transparente
41
+ for facture in client.customer_invoices.list(
42
+ filter=[filters.gte("date", "2026-01-01")],
43
+ sort="-date",
44
+ ):
45
+ print(facture.invoice_number, facture.currency_amount)
46
+
47
+ # Créer un brouillon, le finaliser, l'envoyer
48
+ facture = client.customer_invoices.create(
49
+ customer_id=123,
50
+ date="2026-07-08",
51
+ deadline="2026-08-07",
52
+ invoice_lines=[{"product_id": 45, "quantity": "2"}],
53
+ )
54
+ client.customer_invoices.finalize(facture.id)
55
+ client.customer_invoices.send_by_email(facture.id)
56
+ ```
57
+
58
+ La version asynchrone offre exactement la même surface :
59
+
60
+ ```python
61
+ from pennylane_sdk import AsyncPennylane
62
+
63
+ async with AsyncPennylane() as client:
64
+ page = await client.customer_invoices.list(limit=100)
65
+ async for facture in page:
66
+ ...
67
+ ```
68
+
69
+ ## Cabinets d'expertise comptable
70
+
71
+ L'API Cabinet permet de travailler sur tout le portefeuille de dossiers clients :
72
+
73
+ ```python
74
+ from pennylane_sdk import PennylaneFirm
75
+
76
+ cabinet = PennylaneFirm() # lit PENNYLANE_FIRM_API_TOKEN
77
+
78
+ for dossier in cabinet.companies.list():
79
+ # Balance générale du dossier sur la période
80
+ for ligne in cabinet.trial_balance.list(
81
+ dossier.id, period_start="2026-01-01", period_end="2026-06-30"
82
+ ):
83
+ print(ligne.number, ligne.debits, ligne.credits)
84
+
85
+ # Export FEC
86
+ export = cabinet.exports.fecs.create(
87
+ dossier.id, period_start="2026-01-01", period_end="2026-12-31"
88
+ )
89
+ ```
90
+
91
+ ## Facturation électronique (réforme 2026)
92
+
93
+ Pennylane est Plateforme Agréée (PA) : l'API couvre l'émission et la réception des factures électroniques, et le SDK aussi.
94
+
95
+ ```python
96
+ # Émettre une facture via la plateforme agréée
97
+ client.customer_invoices.send_to_pa(facture.id)
98
+
99
+ # Importer une facture fournisseur Factur-X / UBL / CII
100
+ client.supplier_invoices.import_e_invoice(file="facture.xml")
101
+
102
+ # Suivre vos immatriculations PA
103
+ client.pa_registrations.list()
104
+ ```
105
+
106
+ ## Ce que couvre le SDK
107
+
108
+ | Domaine | Ressources |
109
+ |---|---|
110
+ | Ventes | factures clients, avoirs, devis, abonnements récurrents, clients, produits, envoi par email ou par PA |
111
+ | Achats | fournisseurs, factures fournisseurs, bons de commande, statuts de paiement |
112
+ | Banque | comptes, transactions, rapprochement avec les factures |
113
+ | Comptabilité | journaux, plan comptable, écritures, lettrage, balance, exercices |
114
+ | Analytique | catégories et axes analytiques sur factures, transactions, écritures |
115
+ | Exports | FEC, grand livre, grand livre analytique |
116
+ | Mandats | SEPA, GoCardless, compte pro |
117
+ | Synchronisation | changelogs par ressource, webhooks (bêta), OAuth 2.0 pour les apps partenaires |
118
+ | Cabinet | dossiers clients, comptabilité, GED, exports, lecture des factures |
119
+
120
+ Gestion des erreurs : une hiérarchie d'exceptions claire (`AuthenticationError`, `ValidationError` avec les détails métier, `RateLimitError` avec `retry_after`...). Voir le [guide des erreurs](https://goatandcow7.github.io/pennylane-sdk/guides/errors-and-retries/).
121
+
122
+ ## Contribuer
123
+
124
+ Les contributions sont bienvenues, en anglais de préférence pour le code et les issues. Voir [CONTRIBUTING.md](CONTRIBUTING.md).
125
+
126
+ ## Licence
127
+
128
+ [MIT](LICENSE). Utilisez-le librement, y compris commercialement.
@@ -0,0 +1,107 @@
1
+ # pennylane-sdk
2
+
3
+ > The unofficial Python SDK for the [Pennylane](https://www.pennylane.com) API, the French accounting and invoicing platform.
4
+
5
+ 🇫🇷 [Version française](README.fr.md)
6
+
7
+ [![CI](https://github.com/GoatAndCow7/pennylane-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/GoatAndCow7/pennylane-sdk/actions/workflows/ci.yml)
8
+ [![PyPI](https://img.shields.io/pypi/v/pennylane-sdk)](https://pypi.org/project/pennylane-sdk/)
9
+ [![Python](https://img.shields.io/pypi/pyversions/pennylane-sdk)](https://pypi.org/project/pennylane-sdk/)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-teal.svg)](LICENSE)
11
+
12
+ **[Documentation](https://goatandcow7.github.io/pennylane-sdk/)** | [API coverage: 213/213 operations](#complete-api-coverage)
13
+
14
+ - **Complete**: every operation of the Company API v2 (165) and the Firm API v1 (48), in sync and async, audited against the official OpenAPI specs in CI.
15
+ - **Typed**: Pydantic models everywhere; monetary amounts are `Decimal`, never floats.
16
+ - **Safe for accounting**: the API has no idempotency, so POST is never retried after a server error. No duplicate invoices from a network hiccup.
17
+ - **Rate-limit proof**: built-in client-side throttling to the official limits, plus `retry-after` aware retries on 429.
18
+ - **Effortless pagination**: iterate a list call, the SDK fetches the pages.
19
+
20
+ > Not affiliated with Pennylane SAS. Unrelated to the PennyLane quantum computing framework (which owns `pennylane` on PyPI; this package is `pennylane-sdk`).
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ pip install pennylane-sdk
26
+ ```
27
+
28
+ Python 3.10+.
29
+
30
+ ## Quickstart
31
+
32
+ Create an API token in Pennylane (**Settings > Connectivity > Developers**), then:
33
+
34
+ ```python
35
+ from pennylane_sdk import Pennylane, filters
36
+
37
+ client = Pennylane() # reads PENNYLANE_API_TOKEN
38
+
39
+ # List and filter, with transparent pagination
40
+ for invoice in client.customer_invoices.list(
41
+ filter=[filters.gte("date", "2026-01-01")],
42
+ sort="-date",
43
+ ):
44
+ print(invoice.invoice_number, invoice.currency_amount)
45
+
46
+ # Create, finalize, send
47
+ invoice = client.customer_invoices.create(
48
+ customer_id=123,
49
+ date="2026-07-08",
50
+ deadline="2026-08-07",
51
+ invoice_lines=[{"product_id": 45, "quantity": "2"}],
52
+ )
53
+ client.customer_invoices.finalize(invoice.id)
54
+ client.customer_invoices.send_by_email(invoice.id)
55
+ ```
56
+
57
+ Async, same surface:
58
+
59
+ ```python
60
+ from pennylane_sdk import AsyncPennylane
61
+
62
+ async with AsyncPennylane() as client:
63
+ page = await client.customer_invoices.list(limit=100)
64
+ async for invoice in page:
65
+ ...
66
+ ```
67
+
68
+ Accounting firms, across the whole portfolio:
69
+
70
+ ```python
71
+ from pennylane_sdk import PennylaneFirm
72
+
73
+ firm = PennylaneFirm() # reads PENNYLANE_FIRM_API_TOKEN
74
+ for company in firm.companies.list():
75
+ for row in firm.trial_balance.list(
76
+ company.id, period_start="2026-01-01", period_end="2026-06-30"
77
+ ):
78
+ ...
79
+ ```
80
+
81
+ French e-invoicing (2026 reform), Pennylane being an accredited Plateforme Agréée:
82
+
83
+ ```python
84
+ client.customer_invoices.send_to_pa(invoice.id) # emit through the PA
85
+ client.supplier_invoices.import_e_invoice(file="factur-x.pdf") # ingest Factur-X/UBL/CII
86
+ ```
87
+
88
+ ## Complete API coverage
89
+
90
+ | API | Operations | Resources |
91
+ |---|---|---|
92
+ | Company v2 | 165/165 | customer and supplier invoices, quotes, customers, products, billing subscriptions, banking and reconciliation, journals, ledger entries, lettering, trial balance, analytics, FEC/GL/AGL exports, SEPA/GoCardless/Pro mandates, e-invoicing, changelogs, webhooks |
93
+ | Firm v1 | 48/48 | client portfolio, accounting, DMS, exports, invoicing (read), banking, analytics, changelogs |
94
+
95
+ Coverage is not a promise: `scripts/check_coverage.py` verifies in CI that every operation in the vendored official OpenAPI specs exists in both the sync and async clients.
96
+
97
+ ## Learn more
98
+
99
+ - [Getting started](https://goatandcow7.github.io/pennylane-sdk/getting-started/)
100
+ - [Guides](https://goatandcow7.github.io/pennylane-sdk/guides/authentication/): authentication, pagination and filtering, errors and retries, invoicing lifecycle, e-invoicing 2026, accounting, Firm API, webhooks, OAuth apps
101
+ - [API reference](https://goatandcow7.github.io/pennylane-sdk/api/clients/)
102
+ - [Examples](examples/)
103
+ - [Contributing](CONTRIBUTING.md)
104
+
105
+ ## License
106
+
107
+ [MIT](LICENSE). Build whatever you want with it.