swipeflow-api 1.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.
- swipeflow_api-1.1.0/LICENSE +15 -0
- swipeflow_api-1.1.0/MANIFEST.in +4 -0
- swipeflow_api-1.1.0/PKG-INFO +568 -0
- swipeflow_api-1.1.0/README.md +524 -0
- swipeflow_api-1.1.0/pyproject.toml +82 -0
- swipeflow_api-1.1.0/requirements.txt +4 -0
- swipeflow_api-1.1.0/setup.cfg +4 -0
- swipeflow_api-1.1.0/setup.py +47 -0
- swipeflow_api-1.1.0/swipeflow_api/__init__.py +63 -0
- swipeflow_api-1.1.0/swipeflow_api/client.py +161 -0
- swipeflow_api-1.1.0/swipeflow_api/exceptions.py +110 -0
- swipeflow_api-1.1.0/swipeflow_api/models.py +211 -0
- swipeflow_api-1.1.0/swipeflow_api/py.typed +0 -0
- swipeflow_api-1.1.0/swipeflow_api/resources.py +412 -0
- swipeflow_api-1.1.0/swipeflow_api.egg-info/PKG-INFO +568 -0
- swipeflow_api-1.1.0/swipeflow_api.egg-info/SOURCES.txt +19 -0
- swipeflow_api-1.1.0/swipeflow_api.egg-info/dependency_links.txt +1 -0
- swipeflow_api-1.1.0/swipeflow_api.egg-info/requires.txt +14 -0
- swipeflow_api-1.1.0/swipeflow_api.egg-info/top_level.txt +1 -0
- swipeflow_api-1.1.0/tests/test_client.py +133 -0
- swipeflow_api-1.1.0/tests/test_models.py +139 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 SwipeFlow
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: swipeflow-api
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Python SDK for SwipeFlow API - Add manual approval steps to your workflows with a Tinder-like swiping interface
|
|
5
|
+
Home-page: https://github.com/swipeflow/swipeflow
|
|
6
|
+
Author: SwipeFlow
|
|
7
|
+
Author-email: SwipeFlow <support@swipeflow.io>
|
|
8
|
+
License: ISC
|
|
9
|
+
Project-URL: Homepage, https://swipeflow.io
|
|
10
|
+
Project-URL: Documentation, https://swipeflow.io/docs
|
|
11
|
+
Project-URL: Repository, https://github.com/swipeflow/swipeflow-api-py
|
|
12
|
+
Project-URL: Issue Tracker, https://github.com/swipeflow/swipeflow-api-py/issues
|
|
13
|
+
Keywords: swipeflow,api,sdk,automation,approval,workflow
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: ISC License (ISCL)
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Operating System :: OS Independent
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: requests>=2.28.0
|
|
28
|
+
Requires-Dist: pydantic>=2.0.0
|
|
29
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
30
|
+
Requires-Dist: typing-extensions>=4.5.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
37
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
40
|
+
Dynamic: author
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
Dynamic: requires-python
|
|
44
|
+
|
|
45
|
+
# SwipeFlow Python SDK
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+

|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
A pythonic, auto-generated SDK for the SwipeFlow API. Add manual approval steps to your automation workflows with a Tinder-like swiping interface.
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- 🚀 **Simple & Pythonic** - Intuitive API that follows Python conventions
|
|
56
|
+
- 🔄 **Auto-Generated** - Built from OpenAPI spec for accuracy and consistency
|
|
57
|
+
- 📦 **Fully Typed** - Complete type hints for IDE autocomplete and type checking
|
|
58
|
+
- ⚡ **Async Ready** - Easy to extend with async/await patterns
|
|
59
|
+
- 🛡️ **Error Handling** - Custom exceptions for different error scenarios
|
|
60
|
+
- 🔑 **Multiple Auth** - Supports API keys and JWT tokens
|
|
61
|
+
- 📋 **Well Documented** - Comprehensive docstrings and examples
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
Install from PyPI:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install swipeflow-api-py
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or install from source:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install -e .
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For development:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install -e ".[dev]"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Quick Start
|
|
84
|
+
|
|
85
|
+
### Basic Usage
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from swipeflow_api import SwipeFlowClient
|
|
89
|
+
|
|
90
|
+
# Initialize client
|
|
91
|
+
client = SwipeFlowClient(api_key="your-api-key")
|
|
92
|
+
|
|
93
|
+
# List projects
|
|
94
|
+
projects = client.projects.list()
|
|
95
|
+
for project in projects:
|
|
96
|
+
print(f"Project: {project['name']}")
|
|
97
|
+
|
|
98
|
+
# Create a new item
|
|
99
|
+
item = client.items.create(
|
|
100
|
+
project_id="project-123",
|
|
101
|
+
title="Approve new user signup",
|
|
102
|
+
content={
|
|
103
|
+
"type": "TEXT",
|
|
104
|
+
"data": {"message": "New user John Doe signed up"}
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
print(f"Item created: {item['id']}")
|
|
108
|
+
|
|
109
|
+
# Approve an item
|
|
110
|
+
client.items.approve(
|
|
111
|
+
project_id="project-123",
|
|
112
|
+
item_id=item['id'],
|
|
113
|
+
comment="User verified"
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Environment Variable
|
|
118
|
+
|
|
119
|
+
Set the API key as an environment variable instead of passing it directly:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
export SWIPEFLOW_API_KEY="your-api-key"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Then initialize without the key:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
client = SwipeFlowClient()
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Context Manager
|
|
132
|
+
|
|
133
|
+
Use the client as a context manager to automatically close connections:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
with SwipeFlowClient(api_key="your-api-key") as client:
|
|
137
|
+
projects = client.projects.list()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API Resources
|
|
141
|
+
|
|
142
|
+
### Projects
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# List projects
|
|
146
|
+
projects = client.projects.list(skip=0, limit=20)
|
|
147
|
+
|
|
148
|
+
# Get a specific project
|
|
149
|
+
project = client.projects.get("project-id")
|
|
150
|
+
|
|
151
|
+
# Create a new project
|
|
152
|
+
project = client.projects.create(
|
|
153
|
+
name="My Project",
|
|
154
|
+
description="Project description"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Update a project
|
|
158
|
+
updated = client.projects.update(
|
|
159
|
+
project_id="project-id",
|
|
160
|
+
name="Updated Name"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Delete a project
|
|
164
|
+
client.projects.delete("project-id")
|
|
165
|
+
|
|
166
|
+
# Add a member to project
|
|
167
|
+
client.projects.add_member(
|
|
168
|
+
project_id="project-id",
|
|
169
|
+
user_id="user-id",
|
|
170
|
+
role="EDITOR" # OWNER, ADMIN, EDITOR, VIEWER
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Remove a member
|
|
174
|
+
client.projects.remove_member("project-id", "user-id")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Items
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
# List items in a project
|
|
181
|
+
items = client.items.list(
|
|
182
|
+
project_id="project-id",
|
|
183
|
+
status="PENDING", # Optional: filter by status
|
|
184
|
+
skip=0,
|
|
185
|
+
limit=20
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Get a specific item
|
|
189
|
+
item = client.items.get("project-id", "item-id")
|
|
190
|
+
|
|
191
|
+
# Create an item
|
|
192
|
+
item = client.items.create(
|
|
193
|
+
project_id="project-id",
|
|
194
|
+
title="Review request",
|
|
195
|
+
content={
|
|
196
|
+
"type": "TEXT",
|
|
197
|
+
"data": {"message": "Please review this document"}
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Update an item
|
|
202
|
+
updated = client.items.update(
|
|
203
|
+
project_id="project-id",
|
|
204
|
+
item_id="item-id",
|
|
205
|
+
title="Updated title"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Delete an item
|
|
209
|
+
client.items.delete("project-id", "item-id")
|
|
210
|
+
|
|
211
|
+
# Approve an item
|
|
212
|
+
client.items.approve(
|
|
213
|
+
project_id="project-id",
|
|
214
|
+
item_id="item-id",
|
|
215
|
+
comment="Looks good!"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# Reject an item
|
|
219
|
+
client.items.reject(
|
|
220
|
+
project_id="project-id",
|
|
221
|
+
item_id="item-id",
|
|
222
|
+
comment="Needs revision"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Request changes
|
|
226
|
+
client.items.request_changes(
|
|
227
|
+
project_id="project-id",
|
|
228
|
+
item_id="item-id",
|
|
229
|
+
comment="Please update section 2"
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# Get item version history
|
|
233
|
+
versions = client.items.get_versions("project-id", "item-id")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Webhooks
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
# List webhooks
|
|
240
|
+
webhooks = client.webhooks.list("project-id")
|
|
241
|
+
|
|
242
|
+
# Get a webhook
|
|
243
|
+
webhook = client.webhooks.get("project-id", "webhook-id")
|
|
244
|
+
|
|
245
|
+
# Create a webhook
|
|
246
|
+
webhook = client.webhooks.create(
|
|
247
|
+
project_id="project-id",
|
|
248
|
+
name="My Webhook",
|
|
249
|
+
url="https://example.com/webhook",
|
|
250
|
+
events=["item.created", "item.approved", "item.rejected"]
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
# Update a webhook
|
|
254
|
+
updated = client.webhooks.update(
|
|
255
|
+
project_id="project-id",
|
|
256
|
+
webhook_id="webhook-id",
|
|
257
|
+
name="Updated name",
|
|
258
|
+
active=True
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Delete a webhook
|
|
262
|
+
client.webhooks.delete("project-id", "webhook-id")
|
|
263
|
+
|
|
264
|
+
# Test a webhook
|
|
265
|
+
result = client.webhooks.test("project-id", "webhook-id")
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### API Keys
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
# List API keys
|
|
272
|
+
keys = client.api_keys.list()
|
|
273
|
+
|
|
274
|
+
# Create a new API key
|
|
275
|
+
key = client.api_keys.create(name="Production Key")
|
|
276
|
+
print(f"Key: {key['key']}") # Save this securely!
|
|
277
|
+
|
|
278
|
+
# Delete an API key
|
|
279
|
+
client.api_keys.delete("key-id")
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Authentication
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
# Get current user profile
|
|
286
|
+
profile = client.auth.get_profile()
|
|
287
|
+
|
|
288
|
+
# Update profile
|
|
289
|
+
updated = client.auth.update_profile(
|
|
290
|
+
name="John Doe",
|
|
291
|
+
avatar_url="https://example.com/avatar.jpg"
|
|
292
|
+
)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Error Handling
|
|
296
|
+
|
|
297
|
+
The SDK provides specific exception classes for different error scenarios:
|
|
298
|
+
|
|
299
|
+
```python
|
|
300
|
+
from swipeflow_api import (
|
|
301
|
+
SwipeFlowError,
|
|
302
|
+
AuthenticationError,
|
|
303
|
+
AuthorizationError,
|
|
304
|
+
NotFoundError,
|
|
305
|
+
ValidationError,
|
|
306
|
+
ServerError,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
try:
|
|
310
|
+
client.items.get("project-id", "item-id")
|
|
311
|
+
except NotFoundError as e:
|
|
312
|
+
print(f"Item not found: {e.message}")
|
|
313
|
+
except AuthenticationError as e:
|
|
314
|
+
print(f"Authentication failed: {e.message}")
|
|
315
|
+
except SwipeFlowError as e:
|
|
316
|
+
print(f"API error: {e.message}")
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Models
|
|
320
|
+
|
|
321
|
+
The SDK includes Pydantic models for type safety:
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
from swipeflow_api.models import (
|
|
325
|
+
Item,
|
|
326
|
+
Project,
|
|
327
|
+
User,
|
|
328
|
+
Webhook,
|
|
329
|
+
ItemStatus,
|
|
330
|
+
DecisionType,
|
|
331
|
+
ProjectRole,
|
|
332
|
+
ContentType,
|
|
333
|
+
WebhookEvent,
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
# Models are used for type hints
|
|
337
|
+
def process_item(item: Item) -> None:
|
|
338
|
+
print(f"Processing {item.title} (status: {item.status})")
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Advanced Configuration
|
|
342
|
+
|
|
343
|
+
### Custom Base URL
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
client = SwipeFlowClient(
|
|
347
|
+
api_key="your-api-key",
|
|
348
|
+
base_url="https://staging-api.swipeflow.io"
|
|
349
|
+
)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Timeout and SSL
|
|
353
|
+
|
|
354
|
+
```python
|
|
355
|
+
client = SwipeFlowClient(
|
|
356
|
+
api_key="your-api-key",
|
|
357
|
+
timeout=60,
|
|
358
|
+
verify_ssl=True # Set to False only in development!
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Direct Request Method
|
|
363
|
+
|
|
364
|
+
For advanced use cases, access the underlying request method:
|
|
365
|
+
|
|
366
|
+
```python
|
|
367
|
+
response = client.request(
|
|
368
|
+
method="POST",
|
|
369
|
+
endpoint="/v1/projects/123/items",
|
|
370
|
+
json_data={"title": "Custom item"},
|
|
371
|
+
params={"custom": "param"}
|
|
372
|
+
)
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Development
|
|
376
|
+
|
|
377
|
+
### Setup Development Environment
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
git clone https://github.com/swipeflow/swipeflow.git
|
|
381
|
+
cd sdk/swipeflow-py-api
|
|
382
|
+
pip install -e ".[dev]"
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Code Quality
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# Format code
|
|
389
|
+
black swipeflow_api/
|
|
390
|
+
|
|
391
|
+
# Sort imports
|
|
392
|
+
isort swipeflow_api/
|
|
393
|
+
|
|
394
|
+
# Lint
|
|
395
|
+
flake8 swipeflow_api/
|
|
396
|
+
|
|
397
|
+
# Type checking
|
|
398
|
+
mypy swipeflow_api/
|
|
399
|
+
|
|
400
|
+
# Run tests
|
|
401
|
+
pytest tests/
|
|
402
|
+
|
|
403
|
+
# Generate coverage report
|
|
404
|
+
pytest --cov=swipeflow_api tests/
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Regenerate from OpenAPI
|
|
408
|
+
|
|
409
|
+
The SDK can be regenerated from the backend's OpenAPI spec:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
# Using Python
|
|
413
|
+
python scripts/generate.py
|
|
414
|
+
|
|
415
|
+
# Using bash
|
|
416
|
+
bash scripts/generate.sh
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Publishing
|
|
420
|
+
|
|
421
|
+
### Build Package
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
python -m build
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Publish to PyPI
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
python -m twine upload dist/*
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Architecture
|
|
434
|
+
|
|
435
|
+
### Project Structure
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
swipeflow-py-api/
|
|
439
|
+
├── swipeflow_api/ # Main package
|
|
440
|
+
│ ├── __init__.py # Public API
|
|
441
|
+
│ ├── client.py # Main client
|
|
442
|
+
│ ├── resources.py # Resource classes
|
|
443
|
+
│ ├── models.py # Pydantic models
|
|
444
|
+
│ ├── exceptions.py # Exception classes
|
|
445
|
+
│ └── generated/ # Auto-generated code (from OpenAPI)
|
|
446
|
+
├── scripts/
|
|
447
|
+
│ ├── generate.py # Generation script
|
|
448
|
+
│ └── generate.sh # Bash generation script
|
|
449
|
+
├── tests/ # Test suite
|
|
450
|
+
├── setup.py # Package setup
|
|
451
|
+
├── pyproject.toml # Modern Python packaging
|
|
452
|
+
└── README.md # This file
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Auto-Generation
|
|
456
|
+
|
|
457
|
+
The client is auto-generated from the OpenAPI spec (`backend/openapi.json`) using OpenAPI Generator. This ensures:
|
|
458
|
+
|
|
459
|
+
- ✅ Consistency with backend API
|
|
460
|
+
- ✅ Type-safe models
|
|
461
|
+
- ✅ Complete API coverage
|
|
462
|
+
- ✅ Automatic updates as API evolves
|
|
463
|
+
|
|
464
|
+
The SDK provides a pythonic wrapper (`client.py`, `resources.py`) on top of generated code for better developer experience.
|
|
465
|
+
|
|
466
|
+
## Examples
|
|
467
|
+
|
|
468
|
+
### Batch Process Items
|
|
469
|
+
|
|
470
|
+
```python
|
|
471
|
+
client = SwipeFlowClient(api_key="key")
|
|
472
|
+
|
|
473
|
+
# Get all pending items
|
|
474
|
+
items = client.items.list(
|
|
475
|
+
project_id="project-123",
|
|
476
|
+
status="PENDING",
|
|
477
|
+
limit=100
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
# Process them
|
|
481
|
+
for item in items:
|
|
482
|
+
if "urgent" in item.get("title", "").lower():
|
|
483
|
+
client.items.approve(
|
|
484
|
+
project_id="project-123",
|
|
485
|
+
item_id=item["id"],
|
|
486
|
+
comment="Urgent - approved"
|
|
487
|
+
)
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Setup Webhooks
|
|
491
|
+
|
|
492
|
+
```python
|
|
493
|
+
# Create webhook for all approval events
|
|
494
|
+
client.webhooks.create(
|
|
495
|
+
project_id="project-123",
|
|
496
|
+
name="Approval Events",
|
|
497
|
+
url="https://myapp.com/webhooks/approvals",
|
|
498
|
+
events=[
|
|
499
|
+
"item.approved",
|
|
500
|
+
"item.rejected",
|
|
501
|
+
"item.change_requested"
|
|
502
|
+
]
|
|
503
|
+
)
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Monitor Project
|
|
507
|
+
|
|
508
|
+
```python
|
|
509
|
+
project = client.projects.get("project-123")
|
|
510
|
+
print(f"Project: {project['name']}")
|
|
511
|
+
print(f"Members: {len(project.get('members', []))}")
|
|
512
|
+
print(f"Items: {project.get('item_count', 0)}")
|
|
513
|
+
print(f"Webhooks: {project.get('webhook_count', 0)}")
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Troubleshooting
|
|
517
|
+
|
|
518
|
+
### "API key not provided"
|
|
519
|
+
|
|
520
|
+
Make sure you're passing the API key or setting the `SWIPEFLOW_API_KEY` environment variable:
|
|
521
|
+
|
|
522
|
+
```python
|
|
523
|
+
# Option 1: Pass directly
|
|
524
|
+
client = SwipeFlowClient(api_key="sk_test_...")
|
|
525
|
+
|
|
526
|
+
# Option 2: Environment variable
|
|
527
|
+
export SWIPEFLOW_API_KEY="sk_test_..."
|
|
528
|
+
client = SwipeFlowClient()
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Network Errors
|
|
532
|
+
|
|
533
|
+
The client includes automatic retry logic for transient failures. For persistent issues:
|
|
534
|
+
|
|
535
|
+
```python
|
|
536
|
+
# Increase timeout
|
|
537
|
+
client = SwipeFlowClient(api_key="key", timeout=60)
|
|
538
|
+
|
|
539
|
+
# Check API status
|
|
540
|
+
# Visit https://status.swipeflow.io/
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Type Checking Issues
|
|
544
|
+
|
|
545
|
+
Ensure you're using Python 3.8+ and install type stubs:
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
pip install types-requests
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## Support
|
|
552
|
+
|
|
553
|
+
- 📖 [Documentation](https://docs.swipeflow.io)
|
|
554
|
+
- 🐛 [Report Issues](https://github.com/swipeflow/swipeflow/issues)
|
|
555
|
+
- 💬 [Discussions](https://github.com/swipeflow/swipeflow/discussions)
|
|
556
|
+
- 📧 [Email](mailto:support@swipeflow.io)
|
|
557
|
+
|
|
558
|
+
## License
|
|
559
|
+
|
|
560
|
+
ISC License - See LICENSE file for details
|
|
561
|
+
|
|
562
|
+
## Contributing
|
|
563
|
+
|
|
564
|
+
Contributions are welcome! Please read our [contributing guidelines](../../CONTRIBUTING.md) first.
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
**Made with ❤️ by [SwipeFlow](https://swipeflow.io)**
|