synapsai 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.
- synapsai-0.1.0/.gitignore +53 -0
- synapsai-0.1.0/PKG-INFO +292 -0
- synapsai-0.1.0/README.md +266 -0
- synapsai-0.1.0/pyproject.toml +44 -0
- synapsai-0.1.0/src/synapsai/__init__.py +165 -0
- synapsai-0.1.0/src/synapsai/_client.py +163 -0
- synapsai-0.1.0/src/synapsai/_errors.py +55 -0
- synapsai-0.1.0/src/synapsai/_multipart.py +38 -0
- synapsai-0.1.0/src/synapsai/_types.py +455 -0
- synapsai-0.1.0/src/synapsai/resources/__init__.py +0 -0
- synapsai-0.1.0/src/synapsai/resources/account.py +89 -0
- synapsai-0.1.0/src/synapsai/resources/health.py +27 -0
- synapsai-0.1.0/src/synapsai/resources/trust.py +31 -0
- synapsai-0.1.0/src/synapsai/resources/verify.py +194 -0
- synapsai-0.1.0/src/synapsai/resources/webhooks.py +91 -0
- synapsai-0.1.0/tests/__init__.py +0 -0
- synapsai-0.1.0/tests/conftest.py +145 -0
- synapsai-0.1.0/tests/test_account.py +72 -0
- synapsai-0.1.0/tests/test_trust.py +20 -0
- synapsai-0.1.0/tests/test_verify.py +152 -0
- synapsai-0.1.0/tests/test_webhooks.py +99 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
.next/
|
|
6
|
+
out/
|
|
7
|
+
|
|
8
|
+
# Environment files (contain private keys)
|
|
9
|
+
.env
|
|
10
|
+
.env.local
|
|
11
|
+
.env.production
|
|
12
|
+
.env.development
|
|
13
|
+
taas-api/.env
|
|
14
|
+
node-client/.env
|
|
15
|
+
|
|
16
|
+
# TaaS runtime data (contains real API keys — never commit)
|
|
17
|
+
taas-api/data/
|
|
18
|
+
|
|
19
|
+
# OS files
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
|
|
23
|
+
# Backup/duplicate files
|
|
24
|
+
*.bak
|
|
25
|
+
*.backup*
|
|
26
|
+
*.original
|
|
27
|
+
*.patch
|
|
28
|
+
*.save
|
|
29
|
+
*.full
|
|
30
|
+
|
|
31
|
+
# macOS duplicate files (Finder copies)
|
|
32
|
+
*\ 2.*
|
|
33
|
+
*\ 3.*
|
|
34
|
+
*\ 2/
|
|
35
|
+
*\ 3/
|
|
36
|
+
|
|
37
|
+
# Hardhat
|
|
38
|
+
contracts/artifacts/
|
|
39
|
+
contracts/cache/
|
|
40
|
+
contracts/node_modules/
|
|
41
|
+
|
|
42
|
+
# Logs
|
|
43
|
+
node-client/logs/
|
|
44
|
+
|
|
45
|
+
# PM2
|
|
46
|
+
.pm2/
|
|
47
|
+
|
|
48
|
+
# IDE
|
|
49
|
+
.vscode/
|
|
50
|
+
.idea/
|
|
51
|
+
|
|
52
|
+
# Next.js
|
|
53
|
+
next-env.d.ts
|
synapsai-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: synapsai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the SynapsAI Truth-as-a-Service API
|
|
5
|
+
Project-URL: Homepage, https://synapsai.org/docs
|
|
6
|
+
Project-URL: Repository, https://github.com/SynapsAINetwork/SynapsAI-Dev
|
|
7
|
+
Author-email: SynapsAI <jonathan@synapsai.org>
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: ai-verification,blockchain,synapsai,taas,trust,verification
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Requires-Dist: httpx>=0.24.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-httpx>=0.22.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=7.4; extra == 'dev'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# synapsai
|
|
28
|
+
|
|
29
|
+
Official Python SDK for the [SynapsAI](https://synapsai.org) Truth-as-a-Service (TaaS) API.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install synapsai
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Requires **Python 3.9+**. Runtime dependency: `httpx` only.
|
|
38
|
+
|
|
39
|
+
## Quickstart
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from synapsai import SynapsAI
|
|
43
|
+
|
|
44
|
+
client = SynapsAI(api_key="taas_your_key")
|
|
45
|
+
# or set SYNAPSAI_API_KEY env var and call SynapsAI() with no arguments
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Get your API key at [synapsai.org/api-access](https://synapsai.org/api-access).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Verification
|
|
53
|
+
|
|
54
|
+
### Image verification
|
|
55
|
+
|
|
56
|
+
Detects AI-generated images, deepfakes, and edits using Hive AI, ELA, EXIF, and Claude Vision. Result committed on-chain.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from pathlib import Path
|
|
60
|
+
from synapsai import SynapsAI
|
|
61
|
+
|
|
62
|
+
client = SynapsAI(api_key="taas_your_key")
|
|
63
|
+
|
|
64
|
+
result = client.verify.image(
|
|
65
|
+
image=Path("photo.jpg"),
|
|
66
|
+
claim="Product photo from supplier",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
print(result.verdict) # 'AUTHENTIC'
|
|
70
|
+
print(result.authenticity_score) # 91 (0-100 integer)
|
|
71
|
+
print(result.raw_scores.hive_ai_generated) # 0.02
|
|
72
|
+
print(result.tx_hash) # on-chain proof
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`raw_scores` exposes every signal so you can apply your own thresholds:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Insurance (conservative)
|
|
79
|
+
if result.raw_scores.hive_ai_generated > 0.99:
|
|
80
|
+
flag_for_review()
|
|
81
|
+
|
|
82
|
+
# News (liberal)
|
|
83
|
+
if result.raw_scores.hive_ai_generated > 0.70:
|
|
84
|
+
flag_for_review()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Claim verification (text)
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
# Submit (returns immediately — verification is async)
|
|
91
|
+
claim = client.verify.claim("Company X reduced CO2 by 500 tons in 2025.")
|
|
92
|
+
print(claim.claim_id) # 94
|
|
93
|
+
print(claim.poll) # '/v1/verify/94'
|
|
94
|
+
|
|
95
|
+
# Poll until verified
|
|
96
|
+
import time
|
|
97
|
+
|
|
98
|
+
def wait_for_verification(claim_id, max_wait=60):
|
|
99
|
+
start = time.time()
|
|
100
|
+
while time.time() - start < max_wait:
|
|
101
|
+
status = client.verify.get(claim_id)
|
|
102
|
+
if status.status != "pending":
|
|
103
|
+
return status
|
|
104
|
+
time.sleep(3)
|
|
105
|
+
raise TimeoutError("Verification timed out")
|
|
106
|
+
|
|
107
|
+
status = wait_for_verification(claim.claim_id)
|
|
108
|
+
print(status.verified) # True
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Document verification
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
result = client.verify.document(document=Path("claim.pdf"))
|
|
115
|
+
print(result.verdict)
|
|
116
|
+
print(result.checks) # [DocumentCheck(name=..., passed=..., detail=...)]
|
|
117
|
+
print(result.ai_detection.is_ai_generated) # False
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Luxury goods authentication
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
result = client.verify.luxury(
|
|
124
|
+
images=[Path("front.jpg"), Path("serial.jpg")],
|
|
125
|
+
brand="Rolex",
|
|
126
|
+
model="Submariner",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
print(result.verdict) # 'AUTHENTIC'
|
|
130
|
+
print(result.confidence) # 92
|
|
131
|
+
print(result.indicators) # VisualAuthIndicators(authentic=[...], suspicious=[])
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Other visual authentication endpoints
|
|
135
|
+
|
|
136
|
+
All accept `image: Path | bytes | BinaryIO` or a list of those.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
client.verify.rx(images=img, drug_name="Advil")
|
|
140
|
+
client.verify.credential(images=img, credential_type="degree")
|
|
141
|
+
client.verify.art(images=img, artist="Monet")
|
|
142
|
+
client.verify.sneakers(images=img, brand="Nike")
|
|
143
|
+
client.verify.cards(images=img, card_type="Pokemon")
|
|
144
|
+
client.verify.wine(images=img, producer="Château Pétrus")
|
|
145
|
+
client.verify.ticket(images=img, event="Super Bowl LX")
|
|
146
|
+
client.verify.jewelry(images=img, metal="gold")
|
|
147
|
+
client.verify.electronics(images=img, brand="Apple")
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Trust Scores
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
trust = client.trust.get("0xWalletAddress")
|
|
156
|
+
print(trust.trust_score) # 590 (neutral=500, range 0-1000)
|
|
157
|
+
print(trust.interpretation) # 'trusted'
|
|
158
|
+
|
|
159
|
+
# Batch
|
|
160
|
+
scores = client.trust.batch(["0xAddr1", "0xAddr2"])
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Webhooks
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# Register
|
|
169
|
+
wh = client.webhooks.create(
|
|
170
|
+
url="https://your-server.com/hooks/synapsai",
|
|
171
|
+
events=["verification.completed"],
|
|
172
|
+
)
|
|
173
|
+
# Store wh.secret securely — shown once
|
|
174
|
+
print(wh.id) # 'wh_abc123'
|
|
175
|
+
print(wh.secret) # 'whsec_...'
|
|
176
|
+
|
|
177
|
+
# Verify incoming events (Flask example)
|
|
178
|
+
import os
|
|
179
|
+
from flask import Flask, request, abort
|
|
180
|
+
|
|
181
|
+
app = Flask(__name__)
|
|
182
|
+
|
|
183
|
+
@app.post("/hooks/synapsai")
|
|
184
|
+
def handle_webhook():
|
|
185
|
+
valid = client.webhooks.verify_signature(
|
|
186
|
+
payload=request.get_data(), # raw bytes — do NOT parse first
|
|
187
|
+
signature=request.headers["X-SynapsAI-Signature"],
|
|
188
|
+
secret=os.environ["SYNAPSAI_WEBHOOK_SECRET"],
|
|
189
|
+
)
|
|
190
|
+
if not valid:
|
|
191
|
+
abort(401)
|
|
192
|
+
event = request.get_json()
|
|
193
|
+
# handle event...
|
|
194
|
+
return "", 200
|
|
195
|
+
|
|
196
|
+
# List / manage
|
|
197
|
+
webhooks = client.webhooks.list()
|
|
198
|
+
client.webhooks.test("wh_abc123")
|
|
199
|
+
client.webhooks.delete("wh_abc123")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Account
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
info = client.account.key_info()
|
|
208
|
+
print(info.plan) # 'growth'
|
|
209
|
+
print(info.company) # 'Acme Insurance'
|
|
210
|
+
|
|
211
|
+
usage = client.account.usage()
|
|
212
|
+
print(usage.total_calls) # 42
|
|
213
|
+
|
|
214
|
+
from datetime import datetime, timezone
|
|
215
|
+
|
|
216
|
+
page = client.account.history(
|
|
217
|
+
type="image",
|
|
218
|
+
limit=50,
|
|
219
|
+
from_=datetime(2026, 5, 1, tzinfo=timezone.utc),
|
|
220
|
+
)
|
|
221
|
+
print(page.total)
|
|
222
|
+
print(page.verifications[0].verdict)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Async client
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
import asyncio
|
|
231
|
+
from synapsai import AsyncSynapsAI
|
|
232
|
+
|
|
233
|
+
async def main():
|
|
234
|
+
async with AsyncSynapsAI(api_key="taas_your_key") as client:
|
|
235
|
+
result = await client.verify.image(image=Path("photo.jpg"))
|
|
236
|
+
print(result.verdict)
|
|
237
|
+
|
|
238
|
+
asyncio.run(main())
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Error handling
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
from synapsai import (
|
|
247
|
+
SynapsAIError,
|
|
248
|
+
AuthError,
|
|
249
|
+
RateLimitError,
|
|
250
|
+
ValidationError,
|
|
251
|
+
NotFoundError,
|
|
252
|
+
ServerError,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
result = client.verify.image(image=Path("photo.jpg"))
|
|
257
|
+
except AuthError:
|
|
258
|
+
print("Invalid API key")
|
|
259
|
+
except RateLimitError as e:
|
|
260
|
+
print(f"Rate limited. Retry after {e.retry_after_ms}ms")
|
|
261
|
+
except ValidationError as e:
|
|
262
|
+
print(f"Bad input: {e.message}")
|
|
263
|
+
except ServerError:
|
|
264
|
+
print("Server error — retries exhausted")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
5xx errors are retried automatically up to `max_retries` times (default 3) with exponential backoff. Set `max_retries=0` to disable.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Environment variable
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
export SYNAPSAI_API_KEY=taas_your_key
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
client = SynapsAI() # picks up SYNAPSAI_API_KEY automatically
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Configuration
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
client = SynapsAI(
|
|
287
|
+
api_key="taas_...", # or SYNAPSAI_API_KEY env var
|
|
288
|
+
base_url="https://api.synapsai.org", # optional override
|
|
289
|
+
max_retries=3, # default 3
|
|
290
|
+
timeout=30.0, # seconds, default 30
|
|
291
|
+
)
|
|
292
|
+
```
|
synapsai-0.1.0/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# synapsai
|
|
2
|
+
|
|
3
|
+
Official Python SDK for the [SynapsAI](https://synapsai.org) Truth-as-a-Service (TaaS) API.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install synapsai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires **Python 3.9+**. Runtime dependency: `httpx` only.
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from synapsai import SynapsAI
|
|
17
|
+
|
|
18
|
+
client = SynapsAI(api_key="taas_your_key")
|
|
19
|
+
# or set SYNAPSAI_API_KEY env var and call SynapsAI() with no arguments
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Get your API key at [synapsai.org/api-access](https://synapsai.org/api-access).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Verification
|
|
27
|
+
|
|
28
|
+
### Image verification
|
|
29
|
+
|
|
30
|
+
Detects AI-generated images, deepfakes, and edits using Hive AI, ELA, EXIF, and Claude Vision. Result committed on-chain.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from synapsai import SynapsAI
|
|
35
|
+
|
|
36
|
+
client = SynapsAI(api_key="taas_your_key")
|
|
37
|
+
|
|
38
|
+
result = client.verify.image(
|
|
39
|
+
image=Path("photo.jpg"),
|
|
40
|
+
claim="Product photo from supplier",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
print(result.verdict) # 'AUTHENTIC'
|
|
44
|
+
print(result.authenticity_score) # 91 (0-100 integer)
|
|
45
|
+
print(result.raw_scores.hive_ai_generated) # 0.02
|
|
46
|
+
print(result.tx_hash) # on-chain proof
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`raw_scores` exposes every signal so you can apply your own thresholds:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
# Insurance (conservative)
|
|
53
|
+
if result.raw_scores.hive_ai_generated > 0.99:
|
|
54
|
+
flag_for_review()
|
|
55
|
+
|
|
56
|
+
# News (liberal)
|
|
57
|
+
if result.raw_scores.hive_ai_generated > 0.70:
|
|
58
|
+
flag_for_review()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Claim verification (text)
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
# Submit (returns immediately — verification is async)
|
|
65
|
+
claim = client.verify.claim("Company X reduced CO2 by 500 tons in 2025.")
|
|
66
|
+
print(claim.claim_id) # 94
|
|
67
|
+
print(claim.poll) # '/v1/verify/94'
|
|
68
|
+
|
|
69
|
+
# Poll until verified
|
|
70
|
+
import time
|
|
71
|
+
|
|
72
|
+
def wait_for_verification(claim_id, max_wait=60):
|
|
73
|
+
start = time.time()
|
|
74
|
+
while time.time() - start < max_wait:
|
|
75
|
+
status = client.verify.get(claim_id)
|
|
76
|
+
if status.status != "pending":
|
|
77
|
+
return status
|
|
78
|
+
time.sleep(3)
|
|
79
|
+
raise TimeoutError("Verification timed out")
|
|
80
|
+
|
|
81
|
+
status = wait_for_verification(claim.claim_id)
|
|
82
|
+
print(status.verified) # True
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Document verification
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
result = client.verify.document(document=Path("claim.pdf"))
|
|
89
|
+
print(result.verdict)
|
|
90
|
+
print(result.checks) # [DocumentCheck(name=..., passed=..., detail=...)]
|
|
91
|
+
print(result.ai_detection.is_ai_generated) # False
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Luxury goods authentication
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
result = client.verify.luxury(
|
|
98
|
+
images=[Path("front.jpg"), Path("serial.jpg")],
|
|
99
|
+
brand="Rolex",
|
|
100
|
+
model="Submariner",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
print(result.verdict) # 'AUTHENTIC'
|
|
104
|
+
print(result.confidence) # 92
|
|
105
|
+
print(result.indicators) # VisualAuthIndicators(authentic=[...], suspicious=[])
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Other visual authentication endpoints
|
|
109
|
+
|
|
110
|
+
All accept `image: Path | bytes | BinaryIO` or a list of those.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
client.verify.rx(images=img, drug_name="Advil")
|
|
114
|
+
client.verify.credential(images=img, credential_type="degree")
|
|
115
|
+
client.verify.art(images=img, artist="Monet")
|
|
116
|
+
client.verify.sneakers(images=img, brand="Nike")
|
|
117
|
+
client.verify.cards(images=img, card_type="Pokemon")
|
|
118
|
+
client.verify.wine(images=img, producer="Château Pétrus")
|
|
119
|
+
client.verify.ticket(images=img, event="Super Bowl LX")
|
|
120
|
+
client.verify.jewelry(images=img, metal="gold")
|
|
121
|
+
client.verify.electronics(images=img, brand="Apple")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Trust Scores
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
trust = client.trust.get("0xWalletAddress")
|
|
130
|
+
print(trust.trust_score) # 590 (neutral=500, range 0-1000)
|
|
131
|
+
print(trust.interpretation) # 'trusted'
|
|
132
|
+
|
|
133
|
+
# Batch
|
|
134
|
+
scores = client.trust.batch(["0xAddr1", "0xAddr2"])
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Webhooks
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
# Register
|
|
143
|
+
wh = client.webhooks.create(
|
|
144
|
+
url="https://your-server.com/hooks/synapsai",
|
|
145
|
+
events=["verification.completed"],
|
|
146
|
+
)
|
|
147
|
+
# Store wh.secret securely — shown once
|
|
148
|
+
print(wh.id) # 'wh_abc123'
|
|
149
|
+
print(wh.secret) # 'whsec_...'
|
|
150
|
+
|
|
151
|
+
# Verify incoming events (Flask example)
|
|
152
|
+
import os
|
|
153
|
+
from flask import Flask, request, abort
|
|
154
|
+
|
|
155
|
+
app = Flask(__name__)
|
|
156
|
+
|
|
157
|
+
@app.post("/hooks/synapsai")
|
|
158
|
+
def handle_webhook():
|
|
159
|
+
valid = client.webhooks.verify_signature(
|
|
160
|
+
payload=request.get_data(), # raw bytes — do NOT parse first
|
|
161
|
+
signature=request.headers["X-SynapsAI-Signature"],
|
|
162
|
+
secret=os.environ["SYNAPSAI_WEBHOOK_SECRET"],
|
|
163
|
+
)
|
|
164
|
+
if not valid:
|
|
165
|
+
abort(401)
|
|
166
|
+
event = request.get_json()
|
|
167
|
+
# handle event...
|
|
168
|
+
return "", 200
|
|
169
|
+
|
|
170
|
+
# List / manage
|
|
171
|
+
webhooks = client.webhooks.list()
|
|
172
|
+
client.webhooks.test("wh_abc123")
|
|
173
|
+
client.webhooks.delete("wh_abc123")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Account
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
info = client.account.key_info()
|
|
182
|
+
print(info.plan) # 'growth'
|
|
183
|
+
print(info.company) # 'Acme Insurance'
|
|
184
|
+
|
|
185
|
+
usage = client.account.usage()
|
|
186
|
+
print(usage.total_calls) # 42
|
|
187
|
+
|
|
188
|
+
from datetime import datetime, timezone
|
|
189
|
+
|
|
190
|
+
page = client.account.history(
|
|
191
|
+
type="image",
|
|
192
|
+
limit=50,
|
|
193
|
+
from_=datetime(2026, 5, 1, tzinfo=timezone.utc),
|
|
194
|
+
)
|
|
195
|
+
print(page.total)
|
|
196
|
+
print(page.verifications[0].verdict)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Async client
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
import asyncio
|
|
205
|
+
from synapsai import AsyncSynapsAI
|
|
206
|
+
|
|
207
|
+
async def main():
|
|
208
|
+
async with AsyncSynapsAI(api_key="taas_your_key") as client:
|
|
209
|
+
result = await client.verify.image(image=Path("photo.jpg"))
|
|
210
|
+
print(result.verdict)
|
|
211
|
+
|
|
212
|
+
asyncio.run(main())
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Error handling
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from synapsai import (
|
|
221
|
+
SynapsAIError,
|
|
222
|
+
AuthError,
|
|
223
|
+
RateLimitError,
|
|
224
|
+
ValidationError,
|
|
225
|
+
NotFoundError,
|
|
226
|
+
ServerError,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
try:
|
|
230
|
+
result = client.verify.image(image=Path("photo.jpg"))
|
|
231
|
+
except AuthError:
|
|
232
|
+
print("Invalid API key")
|
|
233
|
+
except RateLimitError as e:
|
|
234
|
+
print(f"Rate limited. Retry after {e.retry_after_ms}ms")
|
|
235
|
+
except ValidationError as e:
|
|
236
|
+
print(f"Bad input: {e.message}")
|
|
237
|
+
except ServerError:
|
|
238
|
+
print("Server error — retries exhausted")
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
5xx errors are retried automatically up to `max_retries` times (default 3) with exponential backoff. Set `max_retries=0` to disable.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Environment variable
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
export SYNAPSAI_API_KEY=taas_your_key
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
client = SynapsAI() # picks up SYNAPSAI_API_KEY automatically
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Configuration
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
client = SynapsAI(
|
|
261
|
+
api_key="taas_...", # or SYNAPSAI_API_KEY env var
|
|
262
|
+
base_url="https://api.synapsai.org", # optional override
|
|
263
|
+
max_retries=3, # default 3
|
|
264
|
+
timeout=30.0, # seconds, default 30
|
|
265
|
+
)
|
|
266
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "synapsai"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official Python SDK for the SynapsAI Truth-as-a-Service API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "SynapsAI", email = "jonathan@synapsai.org" }]
|
|
13
|
+
keywords = ["synapsai", "verification", "trust", "blockchain", "taas", "ai-verification"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
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
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"httpx>=0.24.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = [
|
|
31
|
+
"pytest>=7.4",
|
|
32
|
+
"pytest-httpx>=0.22.0",
|
|
33
|
+
"pytest-asyncio>=0.21.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://synapsai.org/docs"
|
|
38
|
+
Repository = "https://github.com/SynapsAINetwork/SynapsAI-Dev"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/synapsai"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
asyncio_mode = "auto"
|