kyonis 1.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.
- kyonis-1.0.0/LICENSE +21 -0
- kyonis-1.0.0/PKG-INFO +116 -0
- kyonis-1.0.0/README.md +84 -0
- kyonis-1.0.0/kyonis/__init__.py +7 -0
- kyonis-1.0.0/kyonis/client.py +227 -0
- kyonis-1.0.0/kyonis/crewai_tool.py +40 -0
- kyonis-1.0.0/kyonis/exceptions.py +21 -0
- kyonis-1.0.0/kyonis/langchain_tool.py +92 -0
- kyonis-1.0.0/kyonis.egg-info/PKG-INFO +116 -0
- kyonis-1.0.0/kyonis.egg-info/SOURCES.txt +14 -0
- kyonis-1.0.0/kyonis.egg-info/dependency_links.txt +1 -0
- kyonis-1.0.0/kyonis.egg-info/requires.txt +1 -0
- kyonis-1.0.0/kyonis.egg-info/top_level.txt +1 -0
- kyonis-1.0.0/pyproject.toml +35 -0
- kyonis-1.0.0/setup.cfg +4 -0
- kyonis-1.0.0/setup.py +28 -0
kyonis-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kyonis SAS
|
|
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.
|
kyonis-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kyonis
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python SDK for Kyonis — Agent-native KYC/AML compliance API
|
|
5
|
+
Home-page: https://github.com/compliance-ai/python-sdk
|
|
6
|
+
Author: Compliance AI
|
|
7
|
+
Author-email: Kyonis SAS <sdk@kyonis.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://kyonis.com
|
|
10
|
+
Project-URL: Documentation, https://docs.kyonis.com
|
|
11
|
+
Project-URL: Repository, https://github.com/contactkyonis-droid/kyonis
|
|
12
|
+
Project-URL: Changelog, https://github.com/contactkyonis-droid/kyonis/blob/main/sdk/python/CHANGELOG.md
|
|
13
|
+
Keywords: kyc,aml,compliance,sanctions,regtech,fintech,screening
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: httpx>=0.25.0
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: home-page
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
|
|
33
|
+
# Kyonis Python SDK
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/kyonis/)
|
|
36
|
+
[](https://github.com/contactkyonis-droid/kyonis/actions)
|
|
37
|
+
[](https://opensource.org/licenses/MIT)
|
|
38
|
+
|
|
39
|
+
Agent-native KYC/AML compliance API. Screen sanctions, verify identities, and run due diligence in 3 lines of Python.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install kyonis
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from kyonis import Client
|
|
51
|
+
|
|
52
|
+
client = Client(api_key="ky_sandbox_...")
|
|
53
|
+
|
|
54
|
+
# AML Sanctions Screening (< 500ms)
|
|
55
|
+
result = client.aml.screen(name="John Doe", country="US")
|
|
56
|
+
print(result["risk_level"]) # "clear" | "low" | "medium" | "high" | "critical"
|
|
57
|
+
print(result["reasoning"]) # Human-readable explanation
|
|
58
|
+
|
|
59
|
+
# KYC Verification (< 3s)
|
|
60
|
+
kyc = client.kyc.verify(
|
|
61
|
+
nom="Dupont",
|
|
62
|
+
prenom="Jean",
|
|
63
|
+
date_naissance="1990-01-15",
|
|
64
|
+
nationalite="FR",
|
|
65
|
+
)
|
|
66
|
+
print(kyc["risk_score"])
|
|
67
|
+
print(kyc["reasoning"])
|
|
68
|
+
|
|
69
|
+
# Due Diligence (< 10s)
|
|
70
|
+
dd = client.due_diligence.run(
|
|
71
|
+
entity_name="Acme Corp",
|
|
72
|
+
entity_type="company",
|
|
73
|
+
country="FR",
|
|
74
|
+
depth="enhanced",
|
|
75
|
+
)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Features
|
|
79
|
+
|
|
80
|
+
| Feature | Method | Response Time |
|
|
81
|
+
|---------|--------|---------------|
|
|
82
|
+
| Sanctions Screening | `client.aml.screen()` | < 500ms |
|
|
83
|
+
| KYC Verification | `client.kyc.verify()` | < 3s |
|
|
84
|
+
| Due Diligence | `client.due_diligence.run()` | < 10s |
|
|
85
|
+
| UBO Resolution | `client.ubo.resolve()` | < 5s |
|
|
86
|
+
| Entity Risk | `client.entity.get_risk()` | < 200ms |
|
|
87
|
+
| GDPR Export | `client.gdpr.export()` | - |
|
|
88
|
+
| GDPR Erasure | `client.gdpr.erase()` | - |
|
|
89
|
+
|
|
90
|
+
## Error Handling
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from kyonis import Client, RateLimitError, AuthenticationError
|
|
94
|
+
import time
|
|
95
|
+
|
|
96
|
+
client = Client(api_key="ky_...")
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
result = client.aml.screen(name="Test")
|
|
100
|
+
except AuthenticationError:
|
|
101
|
+
print("Invalid API key")
|
|
102
|
+
except RateLimitError as e:
|
|
103
|
+
print(f"Rate limited. Retry in {e.retry_after}s")
|
|
104
|
+
time.sleep(e.retry_after)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
|
|
109
|
+
- **Dashboard**: https://app.kyonis.com
|
|
110
|
+
- **Documentation**: https://docs.kyonis.com
|
|
111
|
+
- **GitHub**: https://github.com/contactkyonis-droid/kyonis
|
|
112
|
+
- **API Reference**: https://docs.kyonis.com/api
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
kyonis-1.0.0/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Kyonis Python SDK
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/kyonis/)
|
|
4
|
+
[](https://github.com/contactkyonis-droid/kyonis/actions)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
Agent-native KYC/AML compliance API. Screen sanctions, verify identities, and run due diligence in 3 lines of Python.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install kyonis
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from kyonis import Client
|
|
19
|
+
|
|
20
|
+
client = Client(api_key="ky_sandbox_...")
|
|
21
|
+
|
|
22
|
+
# AML Sanctions Screening (< 500ms)
|
|
23
|
+
result = client.aml.screen(name="John Doe", country="US")
|
|
24
|
+
print(result["risk_level"]) # "clear" | "low" | "medium" | "high" | "critical"
|
|
25
|
+
print(result["reasoning"]) # Human-readable explanation
|
|
26
|
+
|
|
27
|
+
# KYC Verification (< 3s)
|
|
28
|
+
kyc = client.kyc.verify(
|
|
29
|
+
nom="Dupont",
|
|
30
|
+
prenom="Jean",
|
|
31
|
+
date_naissance="1990-01-15",
|
|
32
|
+
nationalite="FR",
|
|
33
|
+
)
|
|
34
|
+
print(kyc["risk_score"])
|
|
35
|
+
print(kyc["reasoning"])
|
|
36
|
+
|
|
37
|
+
# Due Diligence (< 10s)
|
|
38
|
+
dd = client.due_diligence.run(
|
|
39
|
+
entity_name="Acme Corp",
|
|
40
|
+
entity_type="company",
|
|
41
|
+
country="FR",
|
|
42
|
+
depth="enhanced",
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
| Feature | Method | Response Time |
|
|
49
|
+
|---------|--------|---------------|
|
|
50
|
+
| Sanctions Screening | `client.aml.screen()` | < 500ms |
|
|
51
|
+
| KYC Verification | `client.kyc.verify()` | < 3s |
|
|
52
|
+
| Due Diligence | `client.due_diligence.run()` | < 10s |
|
|
53
|
+
| UBO Resolution | `client.ubo.resolve()` | < 5s |
|
|
54
|
+
| Entity Risk | `client.entity.get_risk()` | < 200ms |
|
|
55
|
+
| GDPR Export | `client.gdpr.export()` | - |
|
|
56
|
+
| GDPR Erasure | `client.gdpr.erase()` | - |
|
|
57
|
+
|
|
58
|
+
## Error Handling
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from kyonis import Client, RateLimitError, AuthenticationError
|
|
62
|
+
import time
|
|
63
|
+
|
|
64
|
+
client = Client(api_key="ky_...")
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
result = client.aml.screen(name="Test")
|
|
68
|
+
except AuthenticationError:
|
|
69
|
+
print("Invalid API key")
|
|
70
|
+
except RateLimitError as e:
|
|
71
|
+
print(f"Rate limited. Retry in {e.retry_after}s")
|
|
72
|
+
time.sleep(e.retry_after)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Links
|
|
76
|
+
|
|
77
|
+
- **Dashboard**: https://app.kyonis.com
|
|
78
|
+
- **Documentation**: https://docs.kyonis.com
|
|
79
|
+
- **GitHub**: https://github.com/contactkyonis-droid/kyonis
|
|
80
|
+
- **API Reference**: https://docs.kyonis.com/api
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""Kyonis — Agent-native KYC/AML compliance SDK."""
|
|
2
|
+
|
|
3
|
+
from kyonis.client import Client
|
|
4
|
+
from kyonis.exceptions import KyonisError, AuthenticationError, RateLimitError, NotFoundError
|
|
5
|
+
|
|
6
|
+
__version__ = "1.0.0"
|
|
7
|
+
__all__ = ["Client", "KyonisError", "AuthenticationError", "RateLimitError", "NotFoundError"]
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""Kyonis API client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from kyonis.exceptions import KyonisError, AuthenticationError, RateLimitError, NotFoundError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
_DEFAULT_BASE_URL = "https://api.kyonis.com"
|
|
11
|
+
_DEFAULT_TIMEOUT = 30.0
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _Resource:
|
|
15
|
+
def __init__(self, client: Client):
|
|
16
|
+
self._client = client
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AML(_Resource):
|
|
20
|
+
def screen(
|
|
21
|
+
self,
|
|
22
|
+
name: str,
|
|
23
|
+
country: str | None = None,
|
|
24
|
+
date_of_birth: str | None = None,
|
|
25
|
+
entity_type: str = "person",
|
|
26
|
+
) -> dict:
|
|
27
|
+
"""Screen a name against OFAC, EU, UN, HMT sanctions lists.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
name: Full name to screen.
|
|
31
|
+
country: ISO 3166-1 alpha-2 country code.
|
|
32
|
+
date_of_birth: Date of birth (YYYY-MM-DD).
|
|
33
|
+
entity_type: "person" or "company".
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Screening result with matches, risk_score, and reasoning.
|
|
37
|
+
"""
|
|
38
|
+
payload = {"name": name, "entity_type": entity_type}
|
|
39
|
+
if country:
|
|
40
|
+
payload["country"] = country
|
|
41
|
+
if date_of_birth:
|
|
42
|
+
payload["date_of_birth"] = date_of_birth
|
|
43
|
+
return self._client._post("/v1/aml/screen", payload)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class KYC(_Resource):
|
|
47
|
+
def verify(
|
|
48
|
+
self,
|
|
49
|
+
nom: str,
|
|
50
|
+
prenom: str,
|
|
51
|
+
date_naissance: str,
|
|
52
|
+
nationalite: str = "FR",
|
|
53
|
+
document_type: str | None = None,
|
|
54
|
+
document_number: str | None = None,
|
|
55
|
+
entity_type: str = "person",
|
|
56
|
+
siren: str | None = None,
|
|
57
|
+
) -> dict:
|
|
58
|
+
"""Run a complete KYC verification.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
nom: Last name.
|
|
62
|
+
prenom: First name.
|
|
63
|
+
date_naissance: Date of birth (YYYY-MM-DD).
|
|
64
|
+
nationalite: ISO country code.
|
|
65
|
+
document_type: Optional document type (passport, id_card, etc.).
|
|
66
|
+
document_number: Optional document number.
|
|
67
|
+
entity_type: "person" or "company".
|
|
68
|
+
siren: SIREN number (for companies).
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Verification result with risk_level, risk_score, reasoning.
|
|
72
|
+
"""
|
|
73
|
+
payload = {
|
|
74
|
+
"nom": nom,
|
|
75
|
+
"prenom": prenom,
|
|
76
|
+
"date_naissance": date_naissance,
|
|
77
|
+
"nationalite": nationalite,
|
|
78
|
+
"entity_type": entity_type,
|
|
79
|
+
}
|
|
80
|
+
if document_type:
|
|
81
|
+
payload["document_type"] = document_type
|
|
82
|
+
if document_number:
|
|
83
|
+
payload["document_number"] = document_number
|
|
84
|
+
if siren:
|
|
85
|
+
payload["siren"] = siren
|
|
86
|
+
return self._client._post("/v1/kyc/verify", payload)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class DueDiligence(_Resource):
|
|
90
|
+
def run(
|
|
91
|
+
self,
|
|
92
|
+
entity_name: str,
|
|
93
|
+
entity_type: str = "person",
|
|
94
|
+
country: str | None = None,
|
|
95
|
+
jurisdiction: str | None = None,
|
|
96
|
+
depth: str = "standard",
|
|
97
|
+
) -> dict:
|
|
98
|
+
"""Run enhanced due diligence.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
entity_name: Name of person or company.
|
|
102
|
+
entity_type: "person" or "company".
|
|
103
|
+
country: ISO country code.
|
|
104
|
+
jurisdiction: Jurisdiction for registry checks.
|
|
105
|
+
depth: "basic", "standard", or "enhanced".
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Due diligence report with risk assessment and reasoning.
|
|
109
|
+
"""
|
|
110
|
+
payload = {"entity_name": entity_name, "entity_type": entity_type, "depth": depth}
|
|
111
|
+
if country:
|
|
112
|
+
payload["country"] = country
|
|
113
|
+
if jurisdiction:
|
|
114
|
+
payload["jurisdiction"] = jurisdiction
|
|
115
|
+
return self._client._post("/v1/due-diligence", payload)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Entity(_Resource):
|
|
119
|
+
def get_risk(self, entity_id: str) -> dict:
|
|
120
|
+
"""Get real-time risk score for a monitored entity."""
|
|
121
|
+
return self._client._get(f"/v1/entity/{entity_id}/risk")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class UBO(_Resource):
|
|
125
|
+
def resolve(
|
|
126
|
+
self,
|
|
127
|
+
entity_name: str,
|
|
128
|
+
siren: str | None = None,
|
|
129
|
+
country: str = "FR",
|
|
130
|
+
ownership_threshold: float = 25.0,
|
|
131
|
+
) -> dict:
|
|
132
|
+
"""Resolve Ultimate Beneficial Owners.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
entity_name: Company name.
|
|
136
|
+
siren: SIREN number.
|
|
137
|
+
country: ISO country code.
|
|
138
|
+
ownership_threshold: Minimum ownership percentage (default 25%).
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
UBO chain with ownership percentages and risk flags.
|
|
142
|
+
"""
|
|
143
|
+
payload = {"entity_name": entity_name, "country": country, "ownership_threshold": ownership_threshold}
|
|
144
|
+
if siren:
|
|
145
|
+
payload["siren"] = siren
|
|
146
|
+
return self._client._post("/v1/ubo/resolve", payload)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class GDPR(_Resource):
|
|
150
|
+
def export(self, entity_id: str) -> dict:
|
|
151
|
+
"""Export all data for an entity (RGPD Art. 15)."""
|
|
152
|
+
return self._client._get(f"/v1/gdpr/export/{entity_id}")
|
|
153
|
+
|
|
154
|
+
def erase(self, entity_id: str) -> dict:
|
|
155
|
+
"""Anonymize personal data for an entity (RGPD Art. 17)."""
|
|
156
|
+
return self._client._delete(f"/v1/gdpr/erase/{entity_id}")
|
|
157
|
+
|
|
158
|
+
def processing_record(self) -> dict:
|
|
159
|
+
"""Get the register of processing activities (RGPD Art. 30)."""
|
|
160
|
+
return self._client._get("/v1/gdpr/processing-record")
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class Client:
|
|
164
|
+
"""Kyonis API client.
|
|
165
|
+
|
|
166
|
+
Usage:
|
|
167
|
+
>>> from kyonis import Client
|
|
168
|
+
>>> client = Client(api_key="ky_...")
|
|
169
|
+
>>> result = client.aml.screen(name="John Doe", country="US")
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
def __init__(
|
|
173
|
+
self,
|
|
174
|
+
api_key: str,
|
|
175
|
+
base_url: str = _DEFAULT_BASE_URL,
|
|
176
|
+
timeout: float = _DEFAULT_TIMEOUT,
|
|
177
|
+
):
|
|
178
|
+
self._api_key = api_key
|
|
179
|
+
self._base_url = base_url.rstrip("/")
|
|
180
|
+
self._http = httpx.Client(
|
|
181
|
+
base_url=self._base_url,
|
|
182
|
+
headers={"X-API-Key": api_key, "Content-Type": "application/json"},
|
|
183
|
+
timeout=timeout,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
self.aml = AML(self)
|
|
187
|
+
self.kyc = KYC(self)
|
|
188
|
+
self.due_diligence = DueDiligence(self)
|
|
189
|
+
self.entity = Entity(self)
|
|
190
|
+
self.ubo = UBO(self)
|
|
191
|
+
self.gdpr = GDPR(self)
|
|
192
|
+
|
|
193
|
+
def _handle_response(self, response: httpx.Response) -> dict:
|
|
194
|
+
if response.status_code == 401:
|
|
195
|
+
raise AuthenticationError(response.json().get("detail", {}).get("message", "Authentication failed"))
|
|
196
|
+
if response.status_code == 403:
|
|
197
|
+
raise AuthenticationError(response.json().get("detail", {}).get("message", "Forbidden"))
|
|
198
|
+
if response.status_code == 404:
|
|
199
|
+
raise NotFoundError(response.json().get("detail", {}).get("message", "Not found"))
|
|
200
|
+
if response.status_code == 429:
|
|
201
|
+
detail = response.json().get("detail", {})
|
|
202
|
+
raise RateLimitError(
|
|
203
|
+
detail.get("message", "Rate limit exceeded"),
|
|
204
|
+
retry_after=int(response.headers.get("Retry-After", 60)),
|
|
205
|
+
)
|
|
206
|
+
if response.status_code >= 400:
|
|
207
|
+
detail = response.json().get("detail", response.json()) if response.headers.get("content-type", "").startswith("application/json") else {}
|
|
208
|
+
raise KyonisError(f"API error {response.status_code}: {detail}")
|
|
209
|
+
return response.json()
|
|
210
|
+
|
|
211
|
+
def _get(self, path: str) -> dict:
|
|
212
|
+
return self._handle_response(self._http.get(path))
|
|
213
|
+
|
|
214
|
+
def _post(self, path: str, json: dict) -> dict:
|
|
215
|
+
return self._handle_response(self._http.post(path, json=json))
|
|
216
|
+
|
|
217
|
+
def _delete(self, path: str) -> dict:
|
|
218
|
+
return self._handle_response(self._http.delete(path))
|
|
219
|
+
|
|
220
|
+
def close(self):
|
|
221
|
+
self._http.close()
|
|
222
|
+
|
|
223
|
+
def __enter__(self):
|
|
224
|
+
return self
|
|
225
|
+
|
|
226
|
+
def __exit__(self, *args):
|
|
227
|
+
self.close()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Kyonis tools for CrewAI agents."""
|
|
2
|
+
|
|
3
|
+
from crewai_tools import BaseTool
|
|
4
|
+
from kyonis import Client
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class KyonisAMLScreenTool(BaseTool):
|
|
8
|
+
name: str = "Kyonis AML Screening"
|
|
9
|
+
description: str = (
|
|
10
|
+
"Screen a person or entity against global sanctions lists (OFAC, EU, UN, HMT). "
|
|
11
|
+
"Input should be a JSON string with 'full_name' and optional 'country' fields."
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
def __init__(self, api_key: str):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self.client = Client(api_key=api_key)
|
|
17
|
+
|
|
18
|
+
def _run(self, input_text: str) -> str:
|
|
19
|
+
import json
|
|
20
|
+
data = json.loads(input_text)
|
|
21
|
+
result = self.client.aml.screen(**data)
|
|
22
|
+
return result.to_json()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class KyonisKYCTool(BaseTool):
|
|
26
|
+
name: str = "Kyonis KYC Verification"
|
|
27
|
+
description: str = (
|
|
28
|
+
"Run a complete KYC verification with risk scoring and explainability. "
|
|
29
|
+
"Input: JSON with 'full_name', 'country', optional 'date_of_birth'."
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def __init__(self, api_key: str):
|
|
33
|
+
super().__init__()
|
|
34
|
+
self.client = Client(api_key=api_key)
|
|
35
|
+
|
|
36
|
+
def _run(self, input_text: str) -> str:
|
|
37
|
+
import json
|
|
38
|
+
data = json.loads(input_text)
|
|
39
|
+
result = self.client.kyc.verify(**data)
|
|
40
|
+
return result.to_json()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Kyonis SDK exceptions."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class KyonisError(Exception):
|
|
5
|
+
"""Base exception for all Kyonis SDK errors."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AuthenticationError(KyonisError):
|
|
9
|
+
"""Raised when API key is invalid or missing."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NotFoundError(KyonisError):
|
|
13
|
+
"""Raised when a requested resource is not found."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RateLimitError(KyonisError):
|
|
17
|
+
"""Raised when rate limit is exceeded."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, message: str, retry_after: int = 60):
|
|
20
|
+
super().__init__(message)
|
|
21
|
+
self.retry_after = retry_after
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Kyonis tools for LangChain agents."""
|
|
2
|
+
|
|
3
|
+
from langchain.tools import BaseTool
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from kyonis import Client
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AMLScreenInput(BaseModel):
|
|
10
|
+
full_name: str = Field(description="Full name of the person or entity to screen")
|
|
11
|
+
country: Optional[str] = Field(default=None, description="ISO country code (FR, US, GB...)")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class KyonisAMLScreenTool(BaseTool):
|
|
15
|
+
name: str = "kyonis_aml_screen"
|
|
16
|
+
description: str = (
|
|
17
|
+
"Screen a person or entity against global sanctions lists "
|
|
18
|
+
"(OFAC, EU, UN, HMT). Returns matches with scores and reasoning. "
|
|
19
|
+
"Use when you need to check if someone is sanctioned or flagged."
|
|
20
|
+
)
|
|
21
|
+
args_schema: type = AMLScreenInput
|
|
22
|
+
client: Client = None
|
|
23
|
+
|
|
24
|
+
def __init__(self, api_key: str):
|
|
25
|
+
super().__init__()
|
|
26
|
+
self.client = Client(api_key=api_key)
|
|
27
|
+
|
|
28
|
+
def _run(self, full_name: str, country: str = None) -> str:
|
|
29
|
+
result = self.client.aml.screen(full_name=full_name, country=country)
|
|
30
|
+
return result.to_json()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class KYCVerifyInput(BaseModel):
|
|
34
|
+
full_name: str = Field(description="Full name of the person")
|
|
35
|
+
country: str = Field(description="ISO country code")
|
|
36
|
+
date_of_birth: Optional[str] = Field(default=None, description="Date of birth YYYY-MM-DD")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class KyonisKYCVerifyTool(BaseTool):
|
|
40
|
+
name: str = "kyonis_kyc_verify"
|
|
41
|
+
description: str = (
|
|
42
|
+
"Run a complete KYC verification on a person. Includes sanctions screening, "
|
|
43
|
+
"registry verification, and AI risk scoring with full explainability. "
|
|
44
|
+
"Use when you need to verify someone's identity for compliance."
|
|
45
|
+
)
|
|
46
|
+
args_schema: type = KYCVerifyInput
|
|
47
|
+
client: Client = None
|
|
48
|
+
|
|
49
|
+
def __init__(self, api_key: str):
|
|
50
|
+
super().__init__()
|
|
51
|
+
self.client = Client(api_key=api_key)
|
|
52
|
+
|
|
53
|
+
def _run(self, full_name: str, country: str, date_of_birth: str = None) -> str:
|
|
54
|
+
result = self.client.kyc.verify(
|
|
55
|
+
full_name=full_name, country=country, date_of_birth=date_of_birth
|
|
56
|
+
)
|
|
57
|
+
return result.to_json()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class KyonisDueDiligenceTool(BaseTool):
|
|
61
|
+
name: str = "kyonis_due_diligence"
|
|
62
|
+
description: str = (
|
|
63
|
+
"Run enhanced due diligence on a company. Checks registries, resolves UBO, "
|
|
64
|
+
"screens officers against sanctions, analyzes adverse media. "
|
|
65
|
+
"Use for M&A due diligence, onboarding companies, or compliance reviews."
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def __init__(self, api_key: str):
|
|
69
|
+
super().__init__()
|
|
70
|
+
self.client = Client(api_key=api_key)
|
|
71
|
+
|
|
72
|
+
def _run(self, company_name: str, country: str, siren: str = None) -> str:
|
|
73
|
+
result = self.client.due_diligence.run(
|
|
74
|
+
company_name=company_name, country=country, siren=siren
|
|
75
|
+
)
|
|
76
|
+
return result.to_json()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# Convenience function to get all Kyonis tools
|
|
80
|
+
def get_kyonis_tools(api_key: str) -> list:
|
|
81
|
+
"""Get all Kyonis compliance tools for a LangChain agent.
|
|
82
|
+
|
|
83
|
+
Usage:
|
|
84
|
+
from kyonis.langchain_tool import get_kyonis_tools
|
|
85
|
+
tools = get_kyonis_tools(api_key="sk_...")
|
|
86
|
+
agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS)
|
|
87
|
+
"""
|
|
88
|
+
return [
|
|
89
|
+
KyonisAMLScreenTool(api_key=api_key),
|
|
90
|
+
KyonisKYCVerifyTool(api_key=api_key),
|
|
91
|
+
KyonisDueDiligenceTool(api_key=api_key),
|
|
92
|
+
]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kyonis
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python SDK for Kyonis — Agent-native KYC/AML compliance API
|
|
5
|
+
Home-page: https://github.com/compliance-ai/python-sdk
|
|
6
|
+
Author: Compliance AI
|
|
7
|
+
Author-email: Kyonis SAS <sdk@kyonis.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://kyonis.com
|
|
10
|
+
Project-URL: Documentation, https://docs.kyonis.com
|
|
11
|
+
Project-URL: Repository, https://github.com/contactkyonis-droid/kyonis
|
|
12
|
+
Project-URL: Changelog, https://github.com/contactkyonis-droid/kyonis/blob/main/sdk/python/CHANGELOG.md
|
|
13
|
+
Keywords: kyc,aml,compliance,sanctions,regtech,fintech,screening
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: httpx>=0.25.0
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: home-page
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
|
|
33
|
+
# Kyonis Python SDK
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/kyonis/)
|
|
36
|
+
[](https://github.com/contactkyonis-droid/kyonis/actions)
|
|
37
|
+
[](https://opensource.org/licenses/MIT)
|
|
38
|
+
|
|
39
|
+
Agent-native KYC/AML compliance API. Screen sanctions, verify identities, and run due diligence in 3 lines of Python.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install kyonis
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from kyonis import Client
|
|
51
|
+
|
|
52
|
+
client = Client(api_key="ky_sandbox_...")
|
|
53
|
+
|
|
54
|
+
# AML Sanctions Screening (< 500ms)
|
|
55
|
+
result = client.aml.screen(name="John Doe", country="US")
|
|
56
|
+
print(result["risk_level"]) # "clear" | "low" | "medium" | "high" | "critical"
|
|
57
|
+
print(result["reasoning"]) # Human-readable explanation
|
|
58
|
+
|
|
59
|
+
# KYC Verification (< 3s)
|
|
60
|
+
kyc = client.kyc.verify(
|
|
61
|
+
nom="Dupont",
|
|
62
|
+
prenom="Jean",
|
|
63
|
+
date_naissance="1990-01-15",
|
|
64
|
+
nationalite="FR",
|
|
65
|
+
)
|
|
66
|
+
print(kyc["risk_score"])
|
|
67
|
+
print(kyc["reasoning"])
|
|
68
|
+
|
|
69
|
+
# Due Diligence (< 10s)
|
|
70
|
+
dd = client.due_diligence.run(
|
|
71
|
+
entity_name="Acme Corp",
|
|
72
|
+
entity_type="company",
|
|
73
|
+
country="FR",
|
|
74
|
+
depth="enhanced",
|
|
75
|
+
)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Features
|
|
79
|
+
|
|
80
|
+
| Feature | Method | Response Time |
|
|
81
|
+
|---------|--------|---------------|
|
|
82
|
+
| Sanctions Screening | `client.aml.screen()` | < 500ms |
|
|
83
|
+
| KYC Verification | `client.kyc.verify()` | < 3s |
|
|
84
|
+
| Due Diligence | `client.due_diligence.run()` | < 10s |
|
|
85
|
+
| UBO Resolution | `client.ubo.resolve()` | < 5s |
|
|
86
|
+
| Entity Risk | `client.entity.get_risk()` | < 200ms |
|
|
87
|
+
| GDPR Export | `client.gdpr.export()` | - |
|
|
88
|
+
| GDPR Erasure | `client.gdpr.erase()` | - |
|
|
89
|
+
|
|
90
|
+
## Error Handling
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from kyonis import Client, RateLimitError, AuthenticationError
|
|
94
|
+
import time
|
|
95
|
+
|
|
96
|
+
client = Client(api_key="ky_...")
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
result = client.aml.screen(name="Test")
|
|
100
|
+
except AuthenticationError:
|
|
101
|
+
print("Invalid API key")
|
|
102
|
+
except RateLimitError as e:
|
|
103
|
+
print(f"Rate limited. Retry in {e.retry_after}s")
|
|
104
|
+
time.sleep(e.retry_after)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
|
|
109
|
+
- **Dashboard**: https://app.kyonis.com
|
|
110
|
+
- **Documentation**: https://docs.kyonis.com
|
|
111
|
+
- **GitHub**: https://github.com/contactkyonis-droid/kyonis
|
|
112
|
+
- **API Reference**: https://docs.kyonis.com/api
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
kyonis/__init__.py
|
|
6
|
+
kyonis/client.py
|
|
7
|
+
kyonis/crewai_tool.py
|
|
8
|
+
kyonis/exceptions.py
|
|
9
|
+
kyonis/langchain_tool.py
|
|
10
|
+
kyonis.egg-info/PKG-INFO
|
|
11
|
+
kyonis.egg-info/SOURCES.txt
|
|
12
|
+
kyonis.egg-info/dependency_links.txt
|
|
13
|
+
kyonis.egg-info/requires.txt
|
|
14
|
+
kyonis.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
httpx>=0.25.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
kyonis
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "kyonis"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Python SDK for Kyonis — Agent-native KYC/AML compliance API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{name = "Kyonis SAS", email = "sdk@kyonis.com"}]
|
|
13
|
+
keywords = ["kyc", "aml", "compliance", "sanctions", "regtech", "fintech", "screening"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.9",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Office/Business :: Financial",
|
|
24
|
+
"Topic :: Security",
|
|
25
|
+
]
|
|
26
|
+
dependencies = ["httpx>=0.25.0"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://kyonis.com"
|
|
30
|
+
Documentation = "https://docs.kyonis.com"
|
|
31
|
+
Repository = "https://github.com/contactkyonis-droid/kyonis"
|
|
32
|
+
Changelog = "https://github.com/contactkyonis-droid/kyonis/blob/main/sdk/python/CHANGELOG.md"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
include = ["kyonis*"]
|
kyonis-1.0.0/setup.cfg
ADDED
kyonis-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="compliance-ai",
|
|
5
|
+
version="0.1.0",
|
|
6
|
+
description="Python SDK for the Compliance AI RegTech API",
|
|
7
|
+
long_description="Sync and async Python client for KYC/AML compliance screening.",
|
|
8
|
+
author="Compliance AI",
|
|
9
|
+
author_email="sdk@compliance-ai.com",
|
|
10
|
+
url="https://github.com/compliance-ai/python-sdk",
|
|
11
|
+
packages=find_packages(),
|
|
12
|
+
python_requires=">=3.10",
|
|
13
|
+
install_requires=[
|
|
14
|
+
"httpx>=0.25.0",
|
|
15
|
+
],
|
|
16
|
+
extras_require={
|
|
17
|
+
"dev": ["pytest", "pytest-asyncio"],
|
|
18
|
+
},
|
|
19
|
+
classifiers=[
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"Topic :: Software Development :: Libraries",
|
|
27
|
+
],
|
|
28
|
+
)
|