epsimo-agent 0.1.0 → 0.2.0
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.
- package/README.md +409 -0
- package/SKILL.md +769 -42
- package/package.json +41 -19
- package/references/api_reference.md +802 -34
- package/requirements.txt +4 -2
- package/verify_skill.py +126 -0
- /package/{references → docs}/virtual_db_guide.md +0 -0
- /package/{scripts/test_sdk.py → test_sdk.py} +0 -0
|
@@ -1,34 +1,802 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
###
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
# Epsimo API Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for the Epsimo Agent Platform API v1.0
|
|
4
|
+
|
|
5
|
+
**Base URL:** `https://api.epsimoagents.com`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
1. [Authentication](#authentication)
|
|
12
|
+
2. [HTTP Status Codes](#http-status-codes)
|
|
13
|
+
3. [Error Handling](#error-handling)
|
|
14
|
+
4. [Rate Limits](#rate-limits)
|
|
15
|
+
5. [Projects](#projects)
|
|
16
|
+
6. [Assistants](#assistants)
|
|
17
|
+
7. [Threads](#threads)
|
|
18
|
+
8. [Messages](#messages)
|
|
19
|
+
9. [Files](#files)
|
|
20
|
+
10. [Credits & Billing](#credits--billing)
|
|
21
|
+
11. [Virtual Database](#virtual-database)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Authentication
|
|
26
|
+
|
|
27
|
+
All API requests require authentication using JWT tokens.
|
|
28
|
+
|
|
29
|
+
### POST /auth/signup
|
|
30
|
+
|
|
31
|
+
Register a new user account.
|
|
32
|
+
|
|
33
|
+
**Request:**
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"email": "user@example.com",
|
|
37
|
+
"password": "secure-password"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Response (200):**
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"access_token": "eyJhbG...",
|
|
45
|
+
"token_type": "Bearer",
|
|
46
|
+
"expires_in": 3600,
|
|
47
|
+
"user": {
|
|
48
|
+
"email": "user@example.com",
|
|
49
|
+
"user_id": "usr_..."
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### POST /auth/login
|
|
55
|
+
|
|
56
|
+
Authenticate and receive access token.
|
|
57
|
+
|
|
58
|
+
**Request:**
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"email": "user@example.com",
|
|
62
|
+
"password": "secure-password"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Response (200):**
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"access_token": "eyJhbG...",
|
|
70
|
+
"token": "eyJhbG...",
|
|
71
|
+
"jwt_token": "eyJhbG...",
|
|
72
|
+
"expires_in": 3600
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Error Response (401):**
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"error": "Invalid credentials",
|
|
80
|
+
"detail": "Email or password is incorrect"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### GET /auth/thread-info
|
|
85
|
+
|
|
86
|
+
Get current user information and thread usage.
|
|
87
|
+
|
|
88
|
+
**Headers:**
|
|
89
|
+
```
|
|
90
|
+
Authorization: Bearer <access_token>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Response (200):**
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"email": "user@example.com",
|
|
97
|
+
"user_id": "usr_123",
|
|
98
|
+
"thread_counter": 45,
|
|
99
|
+
"thread_max": 100,
|
|
100
|
+
"subscription_tier": "standard"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Token Refresh
|
|
105
|
+
|
|
106
|
+
Tokens expire after 1 hour. To refresh:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
# Python example
|
|
110
|
+
import requests
|
|
111
|
+
|
|
112
|
+
def refresh_token(expired_token):
|
|
113
|
+
# Re-authenticate with stored credentials
|
|
114
|
+
response = requests.post(
|
|
115
|
+
"https://api.epsimoagents.com/auth/login",
|
|
116
|
+
json={"email": stored_email, "password": stored_password}
|
|
117
|
+
)
|
|
118
|
+
return response.json()["access_token"]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## HTTP Status Codes
|
|
124
|
+
|
|
125
|
+
| Code | Meaning | Common Causes | Recommended Action |
|
|
126
|
+
|------|---------|---------------|-------------------|
|
|
127
|
+
| 200 | Success | Request completed successfully | Continue processing |
|
|
128
|
+
| 201 | Created | Resource created successfully | Capture returned ID |
|
|
129
|
+
| 204 | No Content | Deletion succeeded | Confirm success |
|
|
130
|
+
| 400 | Bad Request | Invalid payload, missing fields | Validate request schema |
|
|
131
|
+
| 401 | Unauthorized | Invalid/expired token | Refresh or re-authenticate |
|
|
132
|
+
| 403 | Forbidden | Insufficient permissions | Check user/project access |
|
|
133
|
+
| 404 | Not Found | Resource doesn't exist | Verify ID is correct |
|
|
134
|
+
| 409 | Conflict | Duplicate resource | Check for existing records |
|
|
135
|
+
| 422 | Validation Error | Schema validation failed | Review error details |
|
|
136
|
+
| 429 | Too Many Requests | Rate limit exceeded | Implement exponential backoff |
|
|
137
|
+
| 500 | Server Error | Backend issue | Retry with exponential backoff |
|
|
138
|
+
| 503 | Service Unavailable | Temporary downtime | Wait and retry |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Error Handling
|
|
143
|
+
|
|
144
|
+
### Standard Error Response Format
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"error": "Error type",
|
|
149
|
+
"detail": "Detailed error message",
|
|
150
|
+
"field": "problematic_field_name",
|
|
151
|
+
"code": "ERROR_CODE"
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Example Error Responses
|
|
156
|
+
|
|
157
|
+
**Validation Error (422):**
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"error": "Validation Error",
|
|
161
|
+
"detail": "Field 'name' is required",
|
|
162
|
+
"field": "name"
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Authentication Error (401):**
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"error": "Unauthorized",
|
|
170
|
+
"detail": "Token has expired or is invalid",
|
|
171
|
+
"code": "TOKEN_EXPIRED"
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Retry Logic with Exponential Backoff
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
import time
|
|
179
|
+
import requests
|
|
180
|
+
from requests.exceptions import HTTPError
|
|
181
|
+
|
|
182
|
+
def make_request_with_retry(url, headers, method="GET", json_data=None, max_retries=5):
|
|
183
|
+
"""Make API request with automatic retry on rate limits and server errors."""
|
|
184
|
+
for attempt in range(max_retries):
|
|
185
|
+
try:
|
|
186
|
+
response = requests.request(method, url, headers=headers, json=json_data)
|
|
187
|
+
response.raise_for_status()
|
|
188
|
+
return response.json() if response.content else None
|
|
189
|
+
|
|
190
|
+
except HTTPError as e:
|
|
191
|
+
if e.response.status_code == 429:
|
|
192
|
+
# Rate limited - exponential backoff
|
|
193
|
+
wait_time = min(60 * (2 ** attempt), 300) # Max 5 minutes
|
|
194
|
+
print(f"Rate limited. Waiting {wait_time}s...")
|
|
195
|
+
time.sleep(wait_time)
|
|
196
|
+
elif e.response.status_code >= 500:
|
|
197
|
+
# Server error - retry with backoff
|
|
198
|
+
wait_time = min(10 * (2 ** attempt), 60) # Max 1 minute
|
|
199
|
+
print(f"Server error. Waiting {wait_time}s...")
|
|
200
|
+
time.sleep(wait_time)
|
|
201
|
+
elif e.response.status_code == 401:
|
|
202
|
+
# Token expired - try to refresh
|
|
203
|
+
print("Token expired. Attempting refresh...")
|
|
204
|
+
raise
|
|
205
|
+
else:
|
|
206
|
+
# Other errors - don't retry
|
|
207
|
+
raise
|
|
208
|
+
|
|
209
|
+
raise Exception(f"Max retries ({max_retries}) exceeded")
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Rate Limits
|
|
215
|
+
|
|
216
|
+
| Tier | Limit |
|
|
217
|
+
|------|-------|
|
|
218
|
+
| Free | 60 requests/minute |
|
|
219
|
+
| Standard | 300 requests/minute |
|
|
220
|
+
| Premium | 1,000 requests/minute |
|
|
221
|
+
|
|
222
|
+
**Rate Limit Headers:**
|
|
223
|
+
```
|
|
224
|
+
X-RateLimit-Limit: 300
|
|
225
|
+
X-RateLimit-Remaining: 245
|
|
226
|
+
X-RateLimit-Reset: 1672531200
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
When rate limited (429), wait and retry with exponential backoff (see [Error Handling](#error-handling)).
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Projects
|
|
234
|
+
|
|
235
|
+
Projects are top-level containers for assistants, threads, and files.
|
|
236
|
+
|
|
237
|
+
### GET /projects/
|
|
238
|
+
|
|
239
|
+
List all projects for the authenticated user.
|
|
240
|
+
|
|
241
|
+
**Headers:**
|
|
242
|
+
```
|
|
243
|
+
Authorization: Bearer <access_token>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Response (200):**
|
|
247
|
+
```json
|
|
248
|
+
[
|
|
249
|
+
{
|
|
250
|
+
"project_id": "proj_abc123",
|
|
251
|
+
"name": "My AI Project",
|
|
252
|
+
"description": "Customer support automation",
|
|
253
|
+
"created_at": "2024-01-15T10:30:00Z",
|
|
254
|
+
"access_token": "proj_token_..."
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### POST /projects/
|
|
260
|
+
|
|
261
|
+
Create a new project.
|
|
262
|
+
|
|
263
|
+
**Request:**
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"name": "My New Project",
|
|
267
|
+
"description": "Optional description",
|
|
268
|
+
"metadata": {
|
|
269
|
+
"custom_field": "value"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Response (201):**
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"project_id": "proj_xyz789",
|
|
278
|
+
"name": "My New Project",
|
|
279
|
+
"description": "Optional description",
|
|
280
|
+
"access_token": "proj_token_...",
|
|
281
|
+
"created_at": "2024-01-15T11:00:00Z"
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### GET /projects/{project_id}
|
|
286
|
+
|
|
287
|
+
Get project details including project-specific access token.
|
|
288
|
+
|
|
289
|
+
**Response (200):**
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"project_id": "proj_abc123",
|
|
293
|
+
"name": "My AI Project",
|
|
294
|
+
"description": "Customer support automation",
|
|
295
|
+
"access_token": "proj_token_...",
|
|
296
|
+
"token": "proj_token_...",
|
|
297
|
+
"jwt_token": "proj_token_...",
|
|
298
|
+
"created_at": "2024-01-15T10:30:00Z"
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Note:** Use the `access_token` from this response for project-scoped operations (assistants, threads, files).
|
|
303
|
+
|
|
304
|
+
### DELETE /projects/{project_id}?confirm=true
|
|
305
|
+
|
|
306
|
+
Delete a project and all associated resources.
|
|
307
|
+
|
|
308
|
+
**Query Parameters:**
|
|
309
|
+
- `confirm=true` (required) - Confirmation flag
|
|
310
|
+
|
|
311
|
+
**Response (204):**
|
|
312
|
+
No content (successful deletion)
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Assistants
|
|
317
|
+
|
|
318
|
+
Assistants are AI agents with specific instructions and capabilities.
|
|
319
|
+
|
|
320
|
+
### GET /assistants/
|
|
321
|
+
|
|
322
|
+
List all assistants in a project.
|
|
323
|
+
|
|
324
|
+
**Headers:**
|
|
325
|
+
```
|
|
326
|
+
Authorization: Bearer <project_access_token>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Response (200):**
|
|
330
|
+
```json
|
|
331
|
+
[
|
|
332
|
+
{
|
|
333
|
+
"assistant_id": "asst_abc123",
|
|
334
|
+
"name": "Support Agent",
|
|
335
|
+
"config": {
|
|
336
|
+
"instructions": "You are a helpful support agent",
|
|
337
|
+
"model": "gpt-4o",
|
|
338
|
+
"configurable": {
|
|
339
|
+
"type": "agent",
|
|
340
|
+
"agent_type": "agent"
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"public": false,
|
|
344
|
+
"created_at": "2024-01-15T10:45:00Z"
|
|
345
|
+
}
|
|
346
|
+
]
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### POST /assistants/
|
|
350
|
+
|
|
351
|
+
Create a new assistant.
|
|
352
|
+
|
|
353
|
+
**Request:**
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"name": "Research Assistant",
|
|
357
|
+
"config": {
|
|
358
|
+
"instructions": "You help with research tasks",
|
|
359
|
+
"model": "gpt-4o",
|
|
360
|
+
"configurable": {
|
|
361
|
+
"type": "agent",
|
|
362
|
+
"agent_type": "agent"
|
|
363
|
+
},
|
|
364
|
+
"tools": [
|
|
365
|
+
{
|
|
366
|
+
"type": "search_tavily",
|
|
367
|
+
"max_results": 5
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"type": "function",
|
|
371
|
+
"name": "update_database",
|
|
372
|
+
"description": "Save structured data",
|
|
373
|
+
"parameters": {
|
|
374
|
+
"type": "object",
|
|
375
|
+
"properties": {
|
|
376
|
+
"key": {"type": "string"},
|
|
377
|
+
"value": {"type": "object"}
|
|
378
|
+
},
|
|
379
|
+
"required": ["key", "value"]
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
},
|
|
384
|
+
"public": false
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Response (201):**
|
|
389
|
+
```json
|
|
390
|
+
{
|
|
391
|
+
"assistant_id": "asst_xyz789",
|
|
392
|
+
"name": "Research Assistant",
|
|
393
|
+
"config": { ... },
|
|
394
|
+
"public": false,
|
|
395
|
+
"created_at": "2024-01-15T11:15:00Z"
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### GET /assistants/{assistant_id}
|
|
400
|
+
|
|
401
|
+
Get assistant details.
|
|
402
|
+
|
|
403
|
+
**Response (200):**
|
|
404
|
+
```json
|
|
405
|
+
{
|
|
406
|
+
"assistant_id": "asst_abc123",
|
|
407
|
+
"name": "Support Agent",
|
|
408
|
+
"config": { ... },
|
|
409
|
+
"public": false,
|
|
410
|
+
"created_at": "2024-01-15T10:45:00Z"
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### DELETE /assistants/{assistant_id}
|
|
415
|
+
|
|
416
|
+
Delete an assistant.
|
|
417
|
+
|
|
418
|
+
**Response (204):**
|
|
419
|
+
No content (successful deletion)
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Threads
|
|
424
|
+
|
|
425
|
+
Threads represent persistent conversation contexts with Virtual Database state.
|
|
426
|
+
|
|
427
|
+
### GET /threads/
|
|
428
|
+
|
|
429
|
+
List all threads in a project.
|
|
430
|
+
|
|
431
|
+
**Headers:**
|
|
432
|
+
```
|
|
433
|
+
Authorization: Bearer <project_access_token>
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Response (200):**
|
|
437
|
+
```json
|
|
438
|
+
[
|
|
439
|
+
{
|
|
440
|
+
"thread_id": "thread_abc123",
|
|
441
|
+
"name": "Customer #1234",
|
|
442
|
+
"assistant_id": "asst_xyz789",
|
|
443
|
+
"metadata": {
|
|
444
|
+
"configurable": {},
|
|
445
|
+
"type": "thread"
|
|
446
|
+
},
|
|
447
|
+
"created_at": "2024-01-15T12:00:00Z"
|
|
448
|
+
}
|
|
449
|
+
]
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### POST /threads/
|
|
453
|
+
|
|
454
|
+
Create a new thread.
|
|
455
|
+
|
|
456
|
+
**Request:**
|
|
457
|
+
```json
|
|
458
|
+
{
|
|
459
|
+
"name": "Customer Support Session",
|
|
460
|
+
"assistant_id": "asst_xyz789",
|
|
461
|
+
"metadata": {
|
|
462
|
+
"configurable": {},
|
|
463
|
+
"type": "thread"
|
|
464
|
+
},
|
|
465
|
+
"configurable": {
|
|
466
|
+
"type": "agent"
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Response (201):**
|
|
472
|
+
```json
|
|
473
|
+
{
|
|
474
|
+
"thread_id": "thread_new123",
|
|
475
|
+
"name": "Customer Support Session",
|
|
476
|
+
"assistant_id": "asst_xyz789",
|
|
477
|
+
"created_at": "2024-01-15T12:30:00Z"
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### GET /threads/{thread_id}
|
|
482
|
+
|
|
483
|
+
Get thread details and messages.
|
|
484
|
+
|
|
485
|
+
**Response (200):**
|
|
486
|
+
```json
|
|
487
|
+
{
|
|
488
|
+
"thread_id": "thread_abc123",
|
|
489
|
+
"name": "Customer #1234",
|
|
490
|
+
"assistant_id": "asst_xyz789",
|
|
491
|
+
"messages": [
|
|
492
|
+
{
|
|
493
|
+
"role": "user",
|
|
494
|
+
"content": "Hello!",
|
|
495
|
+
"timestamp": "2024-01-15T12:01:00Z"
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
"role": "assistant",
|
|
499
|
+
"content": "How can I help you?",
|
|
500
|
+
"timestamp": "2024-01-15T12:01:05Z"
|
|
501
|
+
}
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### POST /threads/{thread_id}/run
|
|
507
|
+
|
|
508
|
+
Send a message and stream the assistant's response.
|
|
509
|
+
|
|
510
|
+
**Request:**
|
|
511
|
+
```json
|
|
512
|
+
{
|
|
513
|
+
"message": "What's the status of my order?",
|
|
514
|
+
"stream": true
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**Response (Streaming):**
|
|
519
|
+
```
|
|
520
|
+
data: {"type": "start", "run_id": "run_123"}
|
|
521
|
+
|
|
522
|
+
data: {"type": "content", "delta": "Your"}
|
|
523
|
+
|
|
524
|
+
data: {"type": "content", "delta": " order"}
|
|
525
|
+
|
|
526
|
+
data: {"type": "tool_call", "name": "database_query", "args": {...}}
|
|
527
|
+
|
|
528
|
+
data: {"type": "done"}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### DELETE /threads/{thread_id}
|
|
532
|
+
|
|
533
|
+
Delete a thread.
|
|
534
|
+
|
|
535
|
+
**Response (204):**
|
|
536
|
+
No content (successful deletion)
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## Messages
|
|
541
|
+
|
|
542
|
+
### GET /threads/{thread_id}/messages
|
|
543
|
+
|
|
544
|
+
Get all messages in a thread.
|
|
545
|
+
|
|
546
|
+
**Query Parameters:**
|
|
547
|
+
- `limit` (optional): Max messages to return (default: 50)
|
|
548
|
+
- `before` (optional): Cursor for pagination
|
|
549
|
+
|
|
550
|
+
**Response (200):**
|
|
551
|
+
```json
|
|
552
|
+
{
|
|
553
|
+
"messages": [
|
|
554
|
+
{
|
|
555
|
+
"message_id": "msg_123",
|
|
556
|
+
"role": "user",
|
|
557
|
+
"content": "Hello",
|
|
558
|
+
"timestamp": "2024-01-15T12:00:00Z"
|
|
559
|
+
}
|
|
560
|
+
],
|
|
561
|
+
"has_more": false
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### POST /threads/{thread_id}/messages
|
|
566
|
+
|
|
567
|
+
Add a message to a thread (without triggering assistant).
|
|
568
|
+
|
|
569
|
+
**Request:**
|
|
570
|
+
```json
|
|
571
|
+
{
|
|
572
|
+
"role": "user",
|
|
573
|
+
"content": "This is a manual message"
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
**Response (201):**
|
|
578
|
+
```json
|
|
579
|
+
{
|
|
580
|
+
"message_id": "msg_new456",
|
|
581
|
+
"role": "user",
|
|
582
|
+
"content": "This is a manual message",
|
|
583
|
+
"timestamp": "2024-01-15T12:45:00Z"
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## Files
|
|
590
|
+
|
|
591
|
+
### GET /files/
|
|
592
|
+
|
|
593
|
+
List all files in a project.
|
|
594
|
+
|
|
595
|
+
**Headers:**
|
|
596
|
+
```
|
|
597
|
+
Authorization: Bearer <project_access_token>
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
**Response (200):**
|
|
601
|
+
```json
|
|
602
|
+
[
|
|
603
|
+
{
|
|
604
|
+
"file_id": "file_abc123",
|
|
605
|
+
"filename": "document.pdf",
|
|
606
|
+
"size": 1024567,
|
|
607
|
+
"mime_type": "application/pdf",
|
|
608
|
+
"uploaded_at": "2024-01-15T13:00:00Z"
|
|
609
|
+
}
|
|
610
|
+
]
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### POST /files/
|
|
614
|
+
|
|
615
|
+
Upload a file.
|
|
616
|
+
|
|
617
|
+
**Request (multipart/form-data):**
|
|
618
|
+
```
|
|
619
|
+
file: <binary file data>
|
|
620
|
+
purpose: "assistants" | "retrieval"
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
**Response (201):**
|
|
624
|
+
```json
|
|
625
|
+
{
|
|
626
|
+
"file_id": "file_new789",
|
|
627
|
+
"filename": "document.pdf",
|
|
628
|
+
"size": 1024567,
|
|
629
|
+
"purpose": "retrieval",
|
|
630
|
+
"uploaded_at": "2024-01-15T13:15:00Z"
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### DELETE /files/{file_id}
|
|
635
|
+
|
|
636
|
+
Delete a file.
|
|
637
|
+
|
|
638
|
+
**Response (204):**
|
|
639
|
+
No content (successful deletion)
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## Credits & Billing
|
|
644
|
+
|
|
645
|
+
### GET /credits/balance
|
|
646
|
+
|
|
647
|
+
Get current thread usage and limits.
|
|
648
|
+
|
|
649
|
+
**Headers:**
|
|
650
|
+
```
|
|
651
|
+
Authorization: Bearer <access_token>
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
**Response (200):**
|
|
655
|
+
```json
|
|
656
|
+
{
|
|
657
|
+
"thread_counter": 45,
|
|
658
|
+
"thread_max": 100,
|
|
659
|
+
"threads_remaining": 55,
|
|
660
|
+
"subscription_tier": "standard"
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### POST /credits/checkout
|
|
665
|
+
|
|
666
|
+
Create a Stripe checkout session for purchasing threads.
|
|
667
|
+
|
|
668
|
+
**Request:**
|
|
669
|
+
```json
|
|
670
|
+
{
|
|
671
|
+
"quantity": 1000,
|
|
672
|
+
"amount": 80.00
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
**Response (200):**
|
|
677
|
+
```json
|
|
678
|
+
{
|
|
679
|
+
"url": "https://checkout.stripe.com/session_...",
|
|
680
|
+
"session_id": "cs_..."
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**Pricing:**
|
|
685
|
+
- < 500 threads: €0.10/thread
|
|
686
|
+
- 500-999 threads: €0.09/thread
|
|
687
|
+
- 1000+ threads: €0.08/thread
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
## Virtual Database
|
|
692
|
+
|
|
693
|
+
Threads can serve as structured, persistent storage.
|
|
694
|
+
|
|
695
|
+
### GET /db/{project_id}/{thread_id}
|
|
696
|
+
|
|
697
|
+
Get all structured data from a thread.
|
|
698
|
+
|
|
699
|
+
**Headers:**
|
|
700
|
+
```
|
|
701
|
+
Authorization: Bearer <project_access_token>
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Response (200):**
|
|
705
|
+
```json
|
|
706
|
+
{
|
|
707
|
+
"user_preferences": {
|
|
708
|
+
"theme": "dark",
|
|
709
|
+
"language": "en"
|
|
710
|
+
},
|
|
711
|
+
"status": "active",
|
|
712
|
+
"last_action": "checkout"
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### GET /db/{project_id}/{thread_id}/{key}
|
|
717
|
+
|
|
718
|
+
Get specific key from thread state.
|
|
719
|
+
|
|
720
|
+
**Response (200):**
|
|
721
|
+
```json
|
|
722
|
+
{
|
|
723
|
+
"theme": "dark",
|
|
724
|
+
"language": "en"
|
|
725
|
+
}
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### PUT /db/{project_id}/{thread_id}/{key}
|
|
729
|
+
|
|
730
|
+
Set a key-value pair in thread state.
|
|
731
|
+
|
|
732
|
+
**Request:**
|
|
733
|
+
```json
|
|
734
|
+
{
|
|
735
|
+
"value": {
|
|
736
|
+
"theme": "light",
|
|
737
|
+
"language": "es"
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
**Response (200):**
|
|
743
|
+
```json
|
|
744
|
+
{
|
|
745
|
+
"success": true,
|
|
746
|
+
"key": "user_preferences",
|
|
747
|
+
"value": {
|
|
748
|
+
"theme": "light",
|
|
749
|
+
"language": "es"
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## Best Practices
|
|
757
|
+
|
|
758
|
+
### 1. Token Management
|
|
759
|
+
- Cache tokens and refresh on 401 errors
|
|
760
|
+
- Store tokens securely (never in version control)
|
|
761
|
+
- Use project-specific tokens for multi-tenant apps
|
|
762
|
+
|
|
763
|
+
### 2. Error Handling
|
|
764
|
+
- Always implement retry logic for 429 and 500+ errors
|
|
765
|
+
- Use exponential backoff with jitter
|
|
766
|
+
- Log errors for debugging
|
|
767
|
+
|
|
768
|
+
### 3. Rate Limiting
|
|
769
|
+
- Implement client-side throttling
|
|
770
|
+
- Respect `X-RateLimit-*` headers
|
|
771
|
+
- Consider upgrading tier for higher limits
|
|
772
|
+
|
|
773
|
+
### 4. Security
|
|
774
|
+
- Use HTTPS for all requests
|
|
775
|
+
- Validate SSL certificates in production
|
|
776
|
+
- Never expose API keys in frontend code
|
|
777
|
+
- Use environment variables for credentials
|
|
778
|
+
|
|
779
|
+
### 5. Performance
|
|
780
|
+
- Use streaming for long-running conversations
|
|
781
|
+
- Implement pagination for large result sets
|
|
782
|
+
- Cache frequently accessed data
|
|
783
|
+
- Batch operations when possible
|
|
784
|
+
|
|
785
|
+
---
|
|
786
|
+
|
|
787
|
+
## Code Examples
|
|
788
|
+
|
|
789
|
+
See [README.md](../README.md) for comprehensive Python SDK examples.
|
|
790
|
+
|
|
791
|
+
---
|
|
792
|
+
|
|
793
|
+
## Support
|
|
794
|
+
|
|
795
|
+
- **GitHub Issues:** https://github.com/thierryteisseire/epsimo-agent/issues
|
|
796
|
+
- **Documentation:** [SKILL.md](../SKILL.md)
|
|
797
|
+
- **Virtual DB Guide:** [docs/virtual_db_guide.md](../docs/virtual_db_guide.md)
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
**API Version:** 1.0
|
|
802
|
+
**Last Updated:** 2024-02-11
|