clipia 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.
- clipia-1.0.0/.gitignore +9 -0
- clipia-1.0.0/LICENSE +21 -0
- clipia-1.0.0/PKG-INFO +239 -0
- clipia-1.0.0/README.md +206 -0
- clipia-1.0.0/clipia/__init__.py +49 -0
- clipia-1.0.0/clipia/_async_client.py +207 -0
- clipia-1.0.0/clipia/_client.py +215 -0
- clipia-1.0.0/clipia/_errors.py +69 -0
- clipia-1.0.0/clipia/_types.py +191 -0
- clipia-1.0.0/clipia/_version.py +8 -0
- clipia-1.0.0/clipia/py.typed +0 -0
- clipia-1.0.0/clipia/webhooks.py +102 -0
- clipia-1.0.0/pyproject.toml +71 -0
- clipia-1.0.0/tests/conftest.py +18 -0
- clipia-1.0.0/tests/test_async_client.py +160 -0
- clipia-1.0.0/tests/test_client.py +321 -0
- clipia-1.0.0/tests/test_webhooks.py +114 -0
clipia-1.0.0/.gitignore
ADDED
clipia-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Clipia (ИП Захаров М. С.)
|
|
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.
|
clipia-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clipia
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for the Clipia public API (image & video generation, fal-style queue).
|
|
5
|
+
Project-URL: Homepage, https://clipia.ai
|
|
6
|
+
Project-URL: Documentation, https://api.clipia.ai
|
|
7
|
+
Project-URL: Source, https://github.com/clipia-ai/clipia-python
|
|
8
|
+
Project-URL: Issues, https://github.com/clipia-ai/clipia-python/issues
|
|
9
|
+
Author-email: Clipia <support@clipia.ai>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,api,clipia,generative-ai,image-generation,image-to-video,mcp,sdk,text-to-image,text-to-video,video-generation
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
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: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Requires-Dist: httpx>=0.27
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# clipia — Python SDK
|
|
35
|
+
|
|
36
|
+
Official Python SDK for the [Clipia](https://clipia.ai) public API: queue-based
|
|
37
|
+
AI image & video generation with a `submit → status → result` flow and signed
|
|
38
|
+
webhooks. The DX mirrors fal.ai, but is Clipia-native (credits, not USD).
|
|
39
|
+
|
|
40
|
+
- Sync (`Clipia`) and async (`AsyncClipia`) clients
|
|
41
|
+
- High-level `subscribe()` that submits and polls until the job finishes
|
|
42
|
+
- Typed responses (`SubmitResponse`, `StatusResponse`, `ResultResponse`, ...)
|
|
43
|
+
- HMAC-SHA256 webhook signature verification
|
|
44
|
+
- Single runtime dependency: [`httpx`](https://www.python-httpx.org/)
|
|
45
|
+
|
|
46
|
+
> Prefer driving Clipia from an AI agent (Claude Code / Cursor) instead of
|
|
47
|
+
> writing code? Clipia ships a hosted **MCP server** — no SDK required. See
|
|
48
|
+
> [Using Clipia via MCP](#using-clipia-via-mcp-claude-code--cursor) below.
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install clipia
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Requires Python 3.9+.
|
|
57
|
+
|
|
58
|
+
## Authentication
|
|
59
|
+
|
|
60
|
+
Create an API key in your Clipia dashboard (`Settings → API keys`). The key is
|
|
61
|
+
shown once — store it as a server-side secret (never ship it to browsers or
|
|
62
|
+
mobile apps). It is sent as `Authorization: Bearer <key>`.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
export CLIPIA_KEY="clipia_live_xxxxxxxxxxxxxxxxxxxxxx"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Keys come in two flavours: `clipia_live_…` (production, charges credits) and
|
|
69
|
+
`clipia_test_…` (sandbox — instant mock results, no credits charged). Use a
|
|
70
|
+
test key to validate your integration before going live.
|
|
71
|
+
|
|
72
|
+
## Quickstart (sync)
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import os
|
|
76
|
+
from clipia import Clipia
|
|
77
|
+
|
|
78
|
+
client = Clipia(api_key=os.environ["CLIPIA_KEY"])
|
|
79
|
+
|
|
80
|
+
# One call: submit + poll until COMPLETED / FAILED.
|
|
81
|
+
result = client.subscribe(
|
|
82
|
+
"nano-banana-2",
|
|
83
|
+
input={"prompt": "a sunset over mountains, cinematic"},
|
|
84
|
+
on_queue_update=lambda s: print("status:", s.status, s.progress),
|
|
85
|
+
)
|
|
86
|
+
print(result.output["images"][0]["url"])
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Manual queue control
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
job = client.submit("nano-banana-2", input={"prompt": "a cat"})
|
|
93
|
+
print(job.request_id, job.cost)
|
|
94
|
+
|
|
95
|
+
status = client.status(job.request_id) # IN_QUEUE | IN_PROGRESS | COMPLETED | FAILED
|
|
96
|
+
result = client.result(job.request_id) # result.pending == True while still running (HTTP 202)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> A generation cannot be canceled: credits are reserved the moment it starts
|
|
100
|
+
> and the underlying compute cannot be interrupted. Submit deliberately — and
|
|
101
|
+
> use a `clipia_test_…` sandbox key while iterating.
|
|
102
|
+
|
|
103
|
+
### Models, cost estimate & account
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
client.models.list() # { "data": [ ... ] }
|
|
107
|
+
client.models.get("nano-banana-2")
|
|
108
|
+
|
|
109
|
+
# Deterministic credit cost for an input, before you submit.
|
|
110
|
+
est = client.models.estimate("seedance-2-fast-t2v", {"prompt": "neon city", "duration": 8})
|
|
111
|
+
print(est.credits)
|
|
112
|
+
|
|
113
|
+
client.account.get() # { "balance": { "credits": ... }, "usage_30d": { ... } }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The client is also a context manager:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
with Clipia(api_key=os.environ["CLIPIA_KEY"]) as client:
|
|
120
|
+
client.account.get()
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Quickstart (async)
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
import asyncio, os
|
|
127
|
+
from clipia import AsyncClipia
|
|
128
|
+
|
|
129
|
+
async def main():
|
|
130
|
+
async with AsyncClipia(api_key=os.environ["CLIPIA_KEY"]) as client:
|
|
131
|
+
result = await client.subscribe(
|
|
132
|
+
"seedance-2-fast-i2v",
|
|
133
|
+
input={"image_url": "https://.../in.png", "duration": 4},
|
|
134
|
+
)
|
|
135
|
+
print(result.output["video"]["url"])
|
|
136
|
+
|
|
137
|
+
asyncio.run(main())
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`on_queue_update` may be a plain function or an `async def` coroutine.
|
|
141
|
+
|
|
142
|
+
## Idempotency
|
|
143
|
+
|
|
144
|
+
`submit()` (and `subscribe()`) automatically attach a UUID v4 `Idempotency-Key`
|
|
145
|
+
header so network retries are safe. Pass your own to control retries:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
client.submit("nano-banana-2", input={"prompt": "x"}, idempotency_key="order-42")
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Webhooks
|
|
152
|
+
|
|
153
|
+
Pass `webhook_url` to `submit()`/`subscribe()` and Clipia will POST the result to
|
|
154
|
+
your server. Always verify the signature on the **raw** request body:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from clipia import verify_signature
|
|
158
|
+
|
|
159
|
+
# In your web handler (Flask/FastAPI/etc.):
|
|
160
|
+
ok = verify_signature(
|
|
161
|
+
secret=WEBHOOK_SIGNING_SECRET, # from your dashboard
|
|
162
|
+
headers=request.headers, # X-Clipia-Signature: t=...,v1=...
|
|
163
|
+
body=raw_request_body, # bytes or str, exactly as received
|
|
164
|
+
tolerance_seconds=300, # freshness window (default 5 min)
|
|
165
|
+
)
|
|
166
|
+
if not ok:
|
|
167
|
+
return ("invalid signature", 400)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
The delivery payload carries `status` `"OK"` (success) or `"ERROR"` (failed).
|
|
171
|
+
Verification is constant-time and rejects deliveries whose timestamp is outside
|
|
172
|
+
the tolerance window. Treat webhooks as **idempotent by `request_id`** —
|
|
173
|
+
deliveries can repeat.
|
|
174
|
+
|
|
175
|
+
## Errors
|
|
176
|
+
|
|
177
|
+
Non-2xx responses raise `ClipiaApiError`:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from clipia import ClipiaApiError
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
client.submit("nano-banana-2", input={"prompt": "x"})
|
|
184
|
+
except ClipiaApiError as e:
|
|
185
|
+
print(e.status, e.code, e.message) # e.g. 402 insufficient_credits "..."
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`subscribe()` raises `ClipiaTimeoutError` (a subclass of `ClipiaApiError`,
|
|
189
|
+
`status=0`, `code="poll_timeout"`) if the job does not reach a terminal status
|
|
190
|
+
within `timeout` seconds.
|
|
191
|
+
|
|
192
|
+
## Using Clipia via MCP (Claude Code / Cursor)
|
|
193
|
+
|
|
194
|
+
Clipia hosts a remote **Model Context Protocol** server, so an AI coding agent
|
|
195
|
+
can generate images/video, poll results, list models, search prompt templates
|
|
196
|
+
and read your balance directly — **no SDK or code required**. The server is
|
|
197
|
+
stateless Streamable HTTP at `https://api.clipia.ai/mcp` and authenticates with
|
|
198
|
+
the same API key (as a Bearer token).
|
|
199
|
+
|
|
200
|
+
Tools exposed: `generate_image`, `generate_video`, `wait_generation`,
|
|
201
|
+
`get_generation`, `list_models`, `get_model`, `get_balance`, `search_templates`.
|
|
202
|
+
|
|
203
|
+
### Claude Code
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
claude mcp add --transport http clipia https://api.clipia.ai/mcp \
|
|
207
|
+
--header "Authorization: Bearer clipia_live_xxxxxxxx"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Cursor
|
|
211
|
+
|
|
212
|
+
Add to `~/.cursor/mcp.json` (or the project's `.cursor/mcp.json`):
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"mcpServers": {
|
|
217
|
+
"clipia": {
|
|
218
|
+
"url": "https://api.clipia.ai/mcp",
|
|
219
|
+
"headers": {
|
|
220
|
+
"Authorization": "Bearer clipia_live_xxxxxxxx"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Use a `clipia_test_…` key first to exercise the integration with instant mock
|
|
228
|
+
results and no credit charges.
|
|
229
|
+
|
|
230
|
+
## Development
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
pip install -e ".[dev]"
|
|
234
|
+
pytest -q
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## License
|
|
238
|
+
|
|
239
|
+
MIT — see [LICENSE](./LICENSE).
|
clipia-1.0.0/README.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# clipia — Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for the [Clipia](https://clipia.ai) public API: queue-based
|
|
4
|
+
AI image & video generation with a `submit → status → result` flow and signed
|
|
5
|
+
webhooks. The DX mirrors fal.ai, but is Clipia-native (credits, not USD).
|
|
6
|
+
|
|
7
|
+
- Sync (`Clipia`) and async (`AsyncClipia`) clients
|
|
8
|
+
- High-level `subscribe()` that submits and polls until the job finishes
|
|
9
|
+
- Typed responses (`SubmitResponse`, `StatusResponse`, `ResultResponse`, ...)
|
|
10
|
+
- HMAC-SHA256 webhook signature verification
|
|
11
|
+
- Single runtime dependency: [`httpx`](https://www.python-httpx.org/)
|
|
12
|
+
|
|
13
|
+
> Prefer driving Clipia from an AI agent (Claude Code / Cursor) instead of
|
|
14
|
+
> writing code? Clipia ships a hosted **MCP server** — no SDK required. See
|
|
15
|
+
> [Using Clipia via MCP](#using-clipia-via-mcp-claude-code--cursor) below.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install clipia
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires Python 3.9+.
|
|
24
|
+
|
|
25
|
+
## Authentication
|
|
26
|
+
|
|
27
|
+
Create an API key in your Clipia dashboard (`Settings → API keys`). The key is
|
|
28
|
+
shown once — store it as a server-side secret (never ship it to browsers or
|
|
29
|
+
mobile apps). It is sent as `Authorization: Bearer <key>`.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
export CLIPIA_KEY="clipia_live_xxxxxxxxxxxxxxxxxxxxxx"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Keys come in two flavours: `clipia_live_…` (production, charges credits) and
|
|
36
|
+
`clipia_test_…` (sandbox — instant mock results, no credits charged). Use a
|
|
37
|
+
test key to validate your integration before going live.
|
|
38
|
+
|
|
39
|
+
## Quickstart (sync)
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import os
|
|
43
|
+
from clipia import Clipia
|
|
44
|
+
|
|
45
|
+
client = Clipia(api_key=os.environ["CLIPIA_KEY"])
|
|
46
|
+
|
|
47
|
+
# One call: submit + poll until COMPLETED / FAILED.
|
|
48
|
+
result = client.subscribe(
|
|
49
|
+
"nano-banana-2",
|
|
50
|
+
input={"prompt": "a sunset over mountains, cinematic"},
|
|
51
|
+
on_queue_update=lambda s: print("status:", s.status, s.progress),
|
|
52
|
+
)
|
|
53
|
+
print(result.output["images"][0]["url"])
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Manual queue control
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
job = client.submit("nano-banana-2", input={"prompt": "a cat"})
|
|
60
|
+
print(job.request_id, job.cost)
|
|
61
|
+
|
|
62
|
+
status = client.status(job.request_id) # IN_QUEUE | IN_PROGRESS | COMPLETED | FAILED
|
|
63
|
+
result = client.result(job.request_id) # result.pending == True while still running (HTTP 202)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> A generation cannot be canceled: credits are reserved the moment it starts
|
|
67
|
+
> and the underlying compute cannot be interrupted. Submit deliberately — and
|
|
68
|
+
> use a `clipia_test_…` sandbox key while iterating.
|
|
69
|
+
|
|
70
|
+
### Models, cost estimate & account
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
client.models.list() # { "data": [ ... ] }
|
|
74
|
+
client.models.get("nano-banana-2")
|
|
75
|
+
|
|
76
|
+
# Deterministic credit cost for an input, before you submit.
|
|
77
|
+
est = client.models.estimate("seedance-2-fast-t2v", {"prompt": "neon city", "duration": 8})
|
|
78
|
+
print(est.credits)
|
|
79
|
+
|
|
80
|
+
client.account.get() # { "balance": { "credits": ... }, "usage_30d": { ... } }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The client is also a context manager:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
with Clipia(api_key=os.environ["CLIPIA_KEY"]) as client:
|
|
87
|
+
client.account.get()
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Quickstart (async)
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import asyncio, os
|
|
94
|
+
from clipia import AsyncClipia
|
|
95
|
+
|
|
96
|
+
async def main():
|
|
97
|
+
async with AsyncClipia(api_key=os.environ["CLIPIA_KEY"]) as client:
|
|
98
|
+
result = await client.subscribe(
|
|
99
|
+
"seedance-2-fast-i2v",
|
|
100
|
+
input={"image_url": "https://.../in.png", "duration": 4},
|
|
101
|
+
)
|
|
102
|
+
print(result.output["video"]["url"])
|
|
103
|
+
|
|
104
|
+
asyncio.run(main())
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`on_queue_update` may be a plain function or an `async def` coroutine.
|
|
108
|
+
|
|
109
|
+
## Idempotency
|
|
110
|
+
|
|
111
|
+
`submit()` (and `subscribe()`) automatically attach a UUID v4 `Idempotency-Key`
|
|
112
|
+
header so network retries are safe. Pass your own to control retries:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
client.submit("nano-banana-2", input={"prompt": "x"}, idempotency_key="order-42")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Webhooks
|
|
119
|
+
|
|
120
|
+
Pass `webhook_url` to `submit()`/`subscribe()` and Clipia will POST the result to
|
|
121
|
+
your server. Always verify the signature on the **raw** request body:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from clipia import verify_signature
|
|
125
|
+
|
|
126
|
+
# In your web handler (Flask/FastAPI/etc.):
|
|
127
|
+
ok = verify_signature(
|
|
128
|
+
secret=WEBHOOK_SIGNING_SECRET, # from your dashboard
|
|
129
|
+
headers=request.headers, # X-Clipia-Signature: t=...,v1=...
|
|
130
|
+
body=raw_request_body, # bytes or str, exactly as received
|
|
131
|
+
tolerance_seconds=300, # freshness window (default 5 min)
|
|
132
|
+
)
|
|
133
|
+
if not ok:
|
|
134
|
+
return ("invalid signature", 400)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The delivery payload carries `status` `"OK"` (success) or `"ERROR"` (failed).
|
|
138
|
+
Verification is constant-time and rejects deliveries whose timestamp is outside
|
|
139
|
+
the tolerance window. Treat webhooks as **idempotent by `request_id`** —
|
|
140
|
+
deliveries can repeat.
|
|
141
|
+
|
|
142
|
+
## Errors
|
|
143
|
+
|
|
144
|
+
Non-2xx responses raise `ClipiaApiError`:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from clipia import ClipiaApiError
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
client.submit("nano-banana-2", input={"prompt": "x"})
|
|
151
|
+
except ClipiaApiError as e:
|
|
152
|
+
print(e.status, e.code, e.message) # e.g. 402 insufficient_credits "..."
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`subscribe()` raises `ClipiaTimeoutError` (a subclass of `ClipiaApiError`,
|
|
156
|
+
`status=0`, `code="poll_timeout"`) if the job does not reach a terminal status
|
|
157
|
+
within `timeout` seconds.
|
|
158
|
+
|
|
159
|
+
## Using Clipia via MCP (Claude Code / Cursor)
|
|
160
|
+
|
|
161
|
+
Clipia hosts a remote **Model Context Protocol** server, so an AI coding agent
|
|
162
|
+
can generate images/video, poll results, list models, search prompt templates
|
|
163
|
+
and read your balance directly — **no SDK or code required**. The server is
|
|
164
|
+
stateless Streamable HTTP at `https://api.clipia.ai/mcp` and authenticates with
|
|
165
|
+
the same API key (as a Bearer token).
|
|
166
|
+
|
|
167
|
+
Tools exposed: `generate_image`, `generate_video`, `wait_generation`,
|
|
168
|
+
`get_generation`, `list_models`, `get_model`, `get_balance`, `search_templates`.
|
|
169
|
+
|
|
170
|
+
### Claude Code
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
claude mcp add --transport http clipia https://api.clipia.ai/mcp \
|
|
174
|
+
--header "Authorization: Bearer clipia_live_xxxxxxxx"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Cursor
|
|
178
|
+
|
|
179
|
+
Add to `~/.cursor/mcp.json` (or the project's `.cursor/mcp.json`):
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"mcpServers": {
|
|
184
|
+
"clipia": {
|
|
185
|
+
"url": "https://api.clipia.ai/mcp",
|
|
186
|
+
"headers": {
|
|
187
|
+
"Authorization": "Bearer clipia_live_xxxxxxxx"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Use a `clipia_test_…` key first to exercise the integration with instant mock
|
|
195
|
+
results and no credit charges.
|
|
196
|
+
|
|
197
|
+
## Development
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pip install -e ".[dev]"
|
|
201
|
+
pytest -q
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Clipia — official Python SDK for the Clipia public API.
|
|
2
|
+
|
|
3
|
+
Quickstart (sync)::
|
|
4
|
+
|
|
5
|
+
from clipia import Clipia
|
|
6
|
+
|
|
7
|
+
client = Clipia(api_key="clipia_live_...")
|
|
8
|
+
result = client.subscribe("nano-banana-2", input={"prompt": "a sunset over mountains"})
|
|
9
|
+
print(result.output)
|
|
10
|
+
|
|
11
|
+
Quickstart (async)::
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
from clipia import AsyncClipia
|
|
15
|
+
|
|
16
|
+
async def main():
|
|
17
|
+
async with AsyncClipia(api_key="clipia_live_...") as client:
|
|
18
|
+
result = await client.subscribe("nano-banana-2", input={"prompt": "a cat"})
|
|
19
|
+
print(result.output)
|
|
20
|
+
|
|
21
|
+
asyncio.run(main())
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from ._async_client import AsyncClipia
|
|
27
|
+
from ._client import Clipia
|
|
28
|
+
from ._errors import ClipiaApiError, ClipiaTimeoutError
|
|
29
|
+
from ._types import (
|
|
30
|
+
EstimateResponse,
|
|
31
|
+
ResultResponse,
|
|
32
|
+
StatusResponse,
|
|
33
|
+
SubmitResponse,
|
|
34
|
+
)
|
|
35
|
+
from ._version import __version__
|
|
36
|
+
from .webhooks import verify_signature
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"Clipia",
|
|
40
|
+
"AsyncClipia",
|
|
41
|
+
"ClipiaApiError",
|
|
42
|
+
"ClipiaTimeoutError",
|
|
43
|
+
"SubmitResponse",
|
|
44
|
+
"StatusResponse",
|
|
45
|
+
"ResultResponse",
|
|
46
|
+
"EstimateResponse",
|
|
47
|
+
"verify_signature",
|
|
48
|
+
"__version__",
|
|
49
|
+
]
|