vynco 2.0.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 (62) hide show
  1. vynco-2.0.0/.github/workflows/ci.yml +49 -0
  2. vynco-2.0.0/.github/workflows/publish.yml +49 -0
  3. vynco-2.0.0/.gitignore +207 -0
  4. vynco-2.0.0/CHANGELOG.md +168 -0
  5. vynco-2.0.0/CLAUDE.md +37 -0
  6. vynco-2.0.0/LICENSE +201 -0
  7. vynco-2.0.0/PKG-INFO +200 -0
  8. vynco-2.0.0/README.md +177 -0
  9. vynco-2.0.0/docs/superpowers/specs/2026-03-17-vynco-python-sdk-design.md +867 -0
  10. vynco-2.0.0/pyproject.toml +61 -0
  11. vynco-2.0.0/src/vynco/__init__.py +166 -0
  12. vynco-2.0.0/src/vynco/_base_client.py +189 -0
  13. vynco-2.0.0/src/vynco/_client.py +267 -0
  14. vynco-2.0.0/src/vynco/_constants.py +7 -0
  15. vynco-2.0.0/src/vynco/_errors.py +68 -0
  16. vynco-2.0.0/src/vynco/_response.py +34 -0
  17. vynco-2.0.0/src/vynco/py.typed +0 -0
  18. vynco-2.0.0/src/vynco/resources/__init__.py +1 -0
  19. vynco-2.0.0/src/vynco/resources/ai.py +93 -0
  20. vynco-2.0.0/src/vynco/resources/analytics.py +216 -0
  21. vynco-2.0.0/src/vynco/resources/api_keys.py +94 -0
  22. vynco-2.0.0/src/vynco/resources/auditors.py +95 -0
  23. vynco-2.0.0/src/vynco/resources/billing.py +59 -0
  24. vynco-2.0.0/src/vynco/resources/changes.py +98 -0
  25. vynco-2.0.0/src/vynco/resources/companies.py +276 -0
  26. vynco-2.0.0/src/vynco/resources/credits.py +84 -0
  27. vynco-2.0.0/src/vynco/resources/dashboard.py +39 -0
  28. vynco-2.0.0/src/vynco/resources/dossiers.py +100 -0
  29. vynco-2.0.0/src/vynco/resources/exports.py +117 -0
  30. vynco-2.0.0/src/vynco/resources/graph.py +88 -0
  31. vynco-2.0.0/src/vynco/resources/health.py +39 -0
  32. vynco-2.0.0/src/vynco/resources/persons.py +42 -0
  33. vynco-2.0.0/src/vynco/resources/screening.py +63 -0
  34. vynco-2.0.0/src/vynco/resources/teams.py +164 -0
  35. vynco-2.0.0/src/vynco/resources/watchlists.py +159 -0
  36. vynco-2.0.0/src/vynco/resources/webhooks.py +200 -0
  37. vynco-2.0.0/src/vynco/types/__init__.py +135 -0
  38. vynco-2.0.0/src/vynco/types/ai.py +46 -0
  39. vynco-2.0.0/src/vynco/types/analytics.py +86 -0
  40. vynco-2.0.0/src/vynco/types/api_keys.py +31 -0
  41. vynco-2.0.0/src/vynco/types/auditors.py +35 -0
  42. vynco-2.0.0/src/vynco/types/billing.py +9 -0
  43. vynco-2.0.0/src/vynco/types/changes.py +29 -0
  44. vynco-2.0.0/src/vynco/types/companies.py +148 -0
  45. vynco-2.0.0/src/vynco/types/credits.py +54 -0
  46. vynco-2.0.0/src/vynco/types/dashboard.py +36 -0
  47. vynco-2.0.0/src/vynco/types/dossiers.py +26 -0
  48. vynco-2.0.0/src/vynco/types/exports.py +24 -0
  49. vynco-2.0.0/src/vynco/types/graph.py +51 -0
  50. vynco-2.0.0/src/vynco/types/health.py +12 -0
  51. vynco-2.0.0/src/vynco/types/persons.py +17 -0
  52. vynco-2.0.0/src/vynco/types/screening.py +28 -0
  53. vynco-2.0.0/src/vynco/types/shared.py +27 -0
  54. vynco-2.0.0/src/vynco/types/teams.py +55 -0
  55. vynco-2.0.0/src/vynco/types/watchlists.py +35 -0
  56. vynco-2.0.0/src/vynco/types/webhooks.py +44 -0
  57. vynco-2.0.0/tests/__init__.py +0 -0
  58. vynco-2.0.0/tests/conftest.py +3 -0
  59. vynco-2.0.0/tests/test_client.py +365 -0
  60. vynco-2.0.0/tests/test_companies.py +190 -0
  61. vynco-2.0.0/tests/test_resources.py +584 -0
  62. vynco-2.0.0/uv.lock +661 -0
@@ -0,0 +1,49 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: astral-sh/setup-uv@v4
16
+ - run: uv sync
17
+ - run: uv run ruff check src/ tests/
18
+ - run: uv run ruff format --check src/ tests/
19
+
20
+ typecheck:
21
+ name: Typecheck
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: astral-sh/setup-uv@v4
26
+ - run: uv sync
27
+ - run: uv run mypy src/
28
+
29
+ test:
30
+ name: Test (Python ${{ matrix.python-version }})
31
+ runs-on: ubuntu-latest
32
+ strategy:
33
+ matrix:
34
+ python-version: ["3.11", "3.12", "3.13"]
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - uses: astral-sh/setup-uv@v4
38
+ with:
39
+ python-version: ${{ matrix.python-version }}
40
+ - run: uv sync
41
+ - run: uv run pytest --cov=vynco --cov-report=term-missing
42
+
43
+ package:
44
+ name: Package
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ - uses: astral-sh/setup-uv@v4
49
+ - run: uv build
@@ -0,0 +1,49 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ id-token: write
10
+ contents: write
11
+
12
+ jobs:
13
+ verify:
14
+ name: Verify
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v4
19
+ - run: uv sync
20
+ - run: uv run ruff check src/ tests/
21
+ - run: uv run ruff format --check src/ tests/
22
+ - run: uv run mypy src/
23
+ - run: uv run pytest
24
+ - run: uv build
25
+
26
+ publish:
27
+ name: Publish
28
+ needs: verify
29
+ runs-on: ubuntu-latest
30
+ environment: pypi
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - uses: astral-sh/setup-uv@v4
34
+ - run: uv build
35
+ - uses: pypa/gh-action-pypi-publish@release/v1
36
+
37
+ release:
38
+ name: GitHub Release
39
+ needs: publish
40
+ runs-on: ubuntu-latest
41
+ permissions:
42
+ contents: write
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ - name: Create GitHub Release
46
+ env:
47
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48
+ TAG_NAME: ${{ github.ref_name }}
49
+ run: gh release create "$TAG_NAME" --generate-notes --title "$TAG_NAME"
vynco-2.0.0/.gitignore ADDED
@@ -0,0 +1,207 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+ #poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ #pdm.lock
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # SageMath parsed files
135
+ *.sage.py
136
+
137
+ # Environments
138
+ .env
139
+ .envrc
140
+ .venv
141
+ env/
142
+ venv/
143
+ ENV/
144
+ env.bak/
145
+ venv.bak/
146
+
147
+ # Spyder project settings
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope project settings
152
+ .ropeproject
153
+
154
+ # mkdocs documentation
155
+ /site
156
+
157
+ # mypy
158
+ .mypy_cache/
159
+ .dmypy.json
160
+ dmypy.json
161
+
162
+ # Pyre type checker
163
+ .pyre/
164
+
165
+ # pytype static type analyzer
166
+ .pytype/
167
+
168
+ # Cython debug symbols
169
+ cython_debug/
170
+
171
+ # PyCharm
172
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
175
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
+ #.idea/
177
+
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ # .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
@@ -0,0 +1,168 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [2.0.0] - 2026-03-31
9
+
10
+ ### Changed
11
+
12
+ - **Breaking**: Base URL changed from `https://api.vynco.ch/api/v1` to `https://api.vynco.ch` — all resource paths now include `/v1/` prefix, matching the Rust SDK
13
+ - **Breaking**: `companies.list()` parameters changed — removed `status`, `auditor_category`, `sort_by`, `sort_desc`; added `changed_since`, `page`, `page_size`
14
+ - **Breaking**: `companies.count()` no longer accepts filter parameters
15
+ - **Breaking**: `companies.statistics()` now returns typed `CompanyStatistics` model
16
+ - **Breaking**: `companies.compare()` now returns typed `CompareResponse` model
17
+ - **Breaking**: `companies.news()` and `companies.reports()` now return typed models and no longer accept `limit` parameter
18
+ - **Breaking**: `companies.relationships()` and `companies.hierarchy()` now return typed models
19
+ - **Breaking**: `persons` resource stripped to single method `board_members(uid)` returning `list[BoardMember]`
20
+ - **Breaking**: `dossiers` resource rewritten — `create(uid, level)`, `list()`, `get(id_or_uid)`, `delete(id)` replace old API
21
+ - **Breaking**: `changes.list()` parameters changed — now accepts `change_type`, `since`, `until`, `company_search`, `page`, `page_size`
22
+ - **Breaking**: `changes.statistics()` now returns typed `ChangeStatistics` model
23
+ - **Breaking**: `analytics` resource rewritten — `cluster()` and `anomalies()` now take `algorithm` parameter; `velocity()` removed; `candidates()` added
24
+ - **Breaking**: `teams.create()` simplified to `name` only; `list_members()` renamed to `members()`; `invite_member()` now returns `Invitation`
25
+ - **Breaking**: `api_keys.create()` parameters changed to `name`, `environment`, `scopes`; returns typed `ApiKeyCreated`
26
+ - **Breaking**: `billing.create_checkout()` `tier` parameter now required; returns typed `SessionUrl`
27
+ - **Breaking**: `credits.balance()` returns typed `CreditBalance`; `credits.usage()` returns `CreditUsage`; `credits.history()` returns `CreditHistory`
28
+ - **Company** model updated — `canton`, `status`, `legal_form` now `Optional`; added `share_capital`, `industry`; removed `address`, `purpose`, `created_at`
29
+ - **ApiKey** model updated — added `environment`, `scopes`, `status`; removed `is_test_key`
30
+ - **Team** model simplified — removed `overage_rate`, `created_at`, `updated_at`
31
+ - **TeamMember** model updated — removed `is_active`, `invited_at`, `joined_at`; added `last_login_at`
32
+ - **CompanyChange** model updated — removed `sogc_id`, `is_reviewed`, `is_flagged`; added `description`, `source`; `company_name` now `Optional`
33
+
34
+ ### Added
35
+
36
+ - **`health`** resource — `check()` for API health status
37
+ - **`auditors`** resource — `history(uid)`, `tenures(min_years, canton, page, page_size)`
38
+ - **`dashboard`** resource — `get()` for admin dashboard data
39
+ - **`screening`** resource — `screen(name, uid, sources)` for sanctions screening
40
+ - **`watchlists`** resource — `list`, `create`, `delete`, `companies`, `add_companies`, `remove_company`, `events`
41
+ - **`webhooks`** resource — `list`, `create`, `update`, `delete`, `test`, `deliveries`
42
+ - **`exports`** resource — `create`, `get`, `download` for bulk data exports
43
+ - **`ai`** resource — `dossier`, `search`, `risk_score` for AI-powered analysis
44
+ - **`graph`** resource — `get`, `export`, `analyze` for network graphs
45
+ - **`companies.events()`** — company event feed (CloudEvents format)
46
+ - **`companies.fingerprint()`** — data fingerprint for a company
47
+ - **`companies.nearby()`** — find companies near a geographic point
48
+ - **`analytics.candidates()`** — audit candidate companies
49
+ - **`teams.billing_summary()`** — now returns typed `BillingSummary`
50
+ - New typed models: `HealthResponse`, `CompanyStatistics`, `EventListResponse`, `CompanyEvent`, `CompareResponse`, `NewsItem`, `CompanyReport`, `Relationship`, `HierarchyResponse`, `Fingerprint`, `NearbyCompany`, `AuditorHistoryResponse`, `AuditorTenure`, `AuditorTenureStats`, `DashboardResponse`, `DataCompleteness`, `PipelineStatus`, `ScreeningResponse`, `ScreeningHit`, `Watchlist`, `WatchlistSummary`, `WatchlistCompaniesResponse`, `AddCompaniesResponse`, `WebhookSubscription`, `CreateWebhookResponse`, `TestDeliveryResponse`, `WebhookDelivery`, `ExportJob`, `ExportDownload`, `DossierResponse`, `AiSearchResponse`, `RiskScoreResponse`, `RiskFactor`, `ApiKeyCreated`, `CreditBalance`, `CreditUsage`, `CreditHistory`, `SessionUrl`, `Invitation`, `BillingSummary`, `MemberUsage`, `ChangeStatistics`, `BoardMember`, `CantonDistribution`, `AuditorMarketShare`, `ClusterResponse`, `AnomalyResponse`, `RfmSegmentsResponse`, `CohortResponse`, `AuditCandidate`, `DossierSummary`, `GraphResponse`, `GraphNode`, `GraphLink`, `NetworkAnalysisResponse`, `NetworkCluster`
51
+
52
+ ### Removed
53
+
54
+ - **`watches`** resource — replaced by `watchlists`
55
+ - **`notifications`** resource — removed (use webhooks/watchlists instead)
56
+ - **`news`** resource (standalone) — company news is now via `companies.news()`
57
+ - **`companies.search()`** (POST) — use `companies.list(query=...)` instead
58
+ - **`companies.batch_get()`** — removed
59
+ - **`persons.list()`**, **`persons.get()`**, **`persons.roles()`**, **`persons.connections()`**, **`persons.network_stats()`** — persons simplified to `board_members()` only
60
+ - **`dossiers.statistics()`**, **`dossiers.generate()`** — replaced by `dossiers.create()`
61
+ - **`changes.by_sogc()`**, **`changes.batch()`**, **`changes.review()`** — removed
62
+ - **`analytics.velocity()`** — removed
63
+ - Typed models: `Person`, `CompanyWatch`, `ChangeNotification`, `CompanyRelationship`
64
+
65
+ ## [1.0.0] - 2026-03-18
66
+
67
+ ### Changed
68
+
69
+ - **Base URL** updated from `/v1` to `/api/v1` to match production API
70
+ - **`companies.search()`** renamed to **`companies.list()`** — the GET list endpoint with filtering
71
+ - **`companies.compare()`** and **`companies.batch_get()`** now use POST with request body
72
+ - **`companies.relationships()`**, **`hierarchy()`**, **`news()`** now return `dict` (unstructured)
73
+ - **`dossiers.generate()`** parameter renamed from `level` to `type` (values: `standard`, `comprehensive`); endpoint moved to `POST /dossiers/{uid}/generate`
74
+ - **`changes.by_company()`** endpoint updated from `/changes/company/{uid}` to `/changes/{uid}`
75
+ - **`analytics`** endpoints now return `dict` instead of typed models (API returns variable structures)
76
+ - **`credits.balance()`** and **`credits.usage()`** now return `dict` instead of typed models
77
+ - **`credits.history()`** now returns `list[CreditLedgerEntry]` instead of `dict`
78
+ - **`billing`** endpoints updated — paths changed to `/billing/checkout-session` and `/billing/portal-session`; return `dict`
79
+ - **`api_keys.create()`** simplified — returns `dict` (full key returned once); `is_test` parameter renamed to `is_test_key`
80
+ - **`teams.create()`** accepts optional `owner_email` and `owner_name`
81
+ - **Company** model updated: removed `legal_seat`, `capital_nominal`, `capital_currency`, `auditor_name`, `registration_date`, `deletion_date`, `data_source`, `last_modified`; added `address`, `auditor_category`, `created_at`, `updated_at`
82
+ - **Person** model simplified to `id`, `name`, `roles`, `companies` (from first_name/last_name + PersonRole objects)
83
+ - **Dossier** model updated to `company_uid`, `company_name`, `summary`, `risk_score`, `generated_at`
84
+ - **CompanyChange** model: removed `source_date`, added `company_name`, `sogc_id`, `is_reviewed`, `is_flagged`
85
+ - **ApiKeyInfo** / **ApiKeyCreated** replaced by single **ApiKey** model with `id`, `name`, `prefix`, `is_test_key`, `created_at`, `last_used_at`
86
+ - **Team** model: added `updated_at`
87
+ - **PaginatedResponse**: removed `total_pages`, `has_previous_page`, `has_next_page`
88
+ - Development status classifier updated from Alpha to Production/Stable
89
+
90
+ ### Added
91
+
92
+ - **`companies.search()`** — new POST full-text search endpoint (FTS5 with Swiss diacritics)
93
+ - **`companies.reports()`** — get company financial reports
94
+ - **`changes.by_sogc()`** — get changes by SOGC publication ID
95
+ - **`changes.batch()`** — batch fetch changes for up to 50 UIDs
96
+ - **`changes.review()`** — mark a change as reviewed
97
+ - **`persons.list()`** — list persons with optional search
98
+ - **`persons.roles()`** — get all roles held by a person
99
+ - **`persons.connections()`** — get person network connections
100
+ - **`persons.board_members()`** — get board members of a company
101
+ - **`persons.network_stats()`** — person network statistics
102
+ - **`dossiers.list()`** — list all generated dossiers
103
+ - **`dossiers.get()`** — get a specific dossier
104
+ - **`dossiers.statistics()`** — dossier generation statistics
105
+ - **`analytics.cohorts()`** — cohort analytics with groupBy/canton params
106
+ - **`analytics.cluster()`** — K-Means clustering (POST)
107
+ - **`analytics.anomalies()`** — anomaly detection (POST)
108
+ - **`analytics.velocity()`** now accepts `days` parameter
109
+ - **`teams.billing_summary()`** — team billing summary
110
+ - **`teams.list_members()`** — list team members
111
+ - **`teams.invite_member()`** — invite a team member
112
+ - **`teams.update_member_role()`** — update member role
113
+ - **`teams.remove_member()`** — remove a team member
114
+ - **Watches** resource (`client.watches`) — `list`, `add`, `remove` company watches
115
+ - **Notifications** resource (`client.notifications`) — `list` change notifications
116
+ - **News** resource (`client.news`) — `recent` news across all companies
117
+ - **CompanyWatch** model — watch subscription with channel (InApp/Webhook/Email)
118
+ - **TeamMember** model — team member with role and invitation status
119
+ - **ChangeNotification** model — change notification record
120
+ - **CreditLedgerEntry** model — credit ledger entry (grant/debit/refund/expire)
121
+ - **ConflictError** (409) and **ServiceUnavailableError** (503) error types
122
+ - **CI/CD pipeline** — GitHub Actions for lint, typecheck, test (Python 3.11/3.12/3.13), and PyPI publishing on version tags
123
+
124
+ ### Removed
125
+
126
+ - **`webhooks`** resource — replaced by `watches` in the API
127
+ - **`users`** resource — removed from the API
128
+ - **`settings`** resource — removed from the API
129
+ - **`companies.persons()`** — use `persons.board_members()` instead
130
+ - **`companies.dossier()`** — use `dossiers.get()` instead
131
+ - **`companies.changes()`** — use `changes.by_company()` instead
132
+ - Typed models: `PersonRole`, `CompanyComparison`, `CompanyNews`, `Webhook`, `WebhookCreated`, `UserProfile`, `CheckoutSessionResponse`, `PortalSessionResponse`, `CreditBalance`, `UsageBreakdown`, `UsageOperation`, `ChangeStatistics`, `RelationshipsResponse`, `CantonAnalytics`, `AuditorAnalytics`, `RfmSegment`
133
+
134
+ ## [0.1.0] - 2026-03-17
135
+
136
+ ### Added
137
+
138
+ - **Async client** (`AsyncClient`) with context manager support
139
+ - **Sync client** (`Client`) with context manager support
140
+ - **12 resource modules** covering the VynCo public API:
141
+ - `companies` — search, get by UID, count, statistics, compare, board members, dossier, relationships, hierarchy, change history, batch get, news
142
+ - `persons` — get by ID, search by name
143
+ - `dossiers` — generate AI company reports (summary/standard/comprehensive)
144
+ - `changes` — list recent changes, get by company, change statistics
145
+ - `credits` — balance, usage breakdown, transaction history
146
+ - `api_keys` — list, create, revoke API keys
147
+ - `billing` — Stripe checkout and portal sessions
148
+ - `webhooks` — list, create, get, update, delete, test
149
+ - `teams` — get current team, create team
150
+ - `users` — get profile, update profile
151
+ - `settings` — get and update user preferences
152
+ - `analytics` — canton analytics, auditor analytics, RFM segmentation, velocity
153
+ - **Pydantic v2 models** with camelCase alias generation for all API types
154
+ - **Response metadata** via `Response[T]` wrapper exposing API headers:
155
+ - `X-Request-Id` — request tracing
156
+ - `X-Credits-Used` — credits consumed
157
+ - `X-Credits-Remaining` — remaining balance
158
+ - `X-Rate-Limit-Limit` — tier rate limit
159
+ - `X-Data-Source` — OGD compliance (Zefix/LINDAS)
160
+ - **Typed error handling** with exception hierarchy mapping HTTP status codes:
161
+ - `AuthenticationError` (401), `InsufficientCreditsError` (402), `ForbiddenError` (403)
162
+ - `NotFoundError` (404), `ValidationError` (400/422), `RateLimitError` (429), `ServerError` (5xx)
163
+ - `ConfigError` (client misconfiguration), `DeserializationError` (response parsing)
164
+ - **Automatic retry** with exponential backoff on 429 and 5xx responses
165
+ - **Retry-After header** support for rate-limited requests
166
+ - **Environment variable** support (`VYNCO_API_KEY`)
167
+ - **PEP 561** type stub marker (`py.typed`)
168
+ - **41 tests** with respx covering configuration, authentication, error mapping, retry logic, response metadata, and all resource operations
vynco-2.0.0/CLAUDE.md ADDED
@@ -0,0 +1,37 @@
1
+ # CLAUDE.md
2
+
3
+ ## Project
4
+
5
+ VynCo Python SDK (`vynco`) — Python client for the VynCo Swiss Corporate Intelligence API.
6
+
7
+ ## Build & Test
8
+
9
+ ```bash
10
+ uv sync # Install all dependencies
11
+ uv run pytest # Run all tests
12
+ uv run pytest -x # Stop on first failure
13
+ uv run pytest -k "test_company" # Run specific tests
14
+ uv run ruff check src/ # Lint
15
+ uv run ruff format src/ # Format
16
+ uv run mypy src/ # Type check
17
+ ```
18
+
19
+ ## Architecture
20
+
21
+ - `src/vynco/` — Package source (src layout)
22
+ - `_constants.py` — Default base URL, timeout, version
23
+ - `_errors.py` — Exception hierarchy (VyncoError → AuthenticationError, etc.)
24
+ - `_response.py` — Response[T] and ResponseMeta dataclasses
25
+ - `_base_client.py` — Shared HTTP logic, retry, error mapping
26
+ - `_client.py` — AsyncClient + Client (sync)
27
+ - `types/` — Pydantic v2 models (one file per domain)
28
+ - `resources/` — Resource classes (async + sync variants per file)
29
+ - `tests/` — pytest + respx tests
30
+
31
+ ## Conventions
32
+
33
+ - All API models use `VyncoModel` base (Pydantic with camelCase alias)
34
+ - Resource methods use keyword-only arguments (not param objects)
35
+ - Both sync and async resource classes live in the same file
36
+ - The `query` Python parameter maps to `search` on the wire
37
+ - Use `from __future__ import annotations` in all modules