@fileverse/api 0.0.1

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/public/llm.txt ADDED
@@ -0,0 +1,621 @@
1
+ # Fileverse API - AI Agent Guide
2
+
3
+ > Fileverse API is a document management system by Fileverse that stores and syncs documents (ddocs) between a local database and blockchain.
4
+
5
+ **Skill Name**: fileverse-api
6
+
7
+ ## How to use this document
8
+
9
+ Fetch this via GET {SERVER_URL}/llm.txt. Use it to discover the server URL, decide API vs CLI mode, then follow the relevant section below.
10
+
11
+ ## Integration checklist
12
+
13
+ 1. Get server URL (from the URL you used to fetch this doc, minus /llm.txt) and apiKey (see API Key Configuration).
14
+ 2. Try GET {SERVER_URL}/ping. If you get 200 and {"reply":"pong"}, use API mode; otherwise use CLI mode.
15
+ 3. In API mode: every request must include apiKey as a query parameter; the path is complete before any query string.
16
+ 4. For create/update: extract ddocId from response.data.ddocId (not from the top level of the response).
17
+ 5. After create or update, poll GET /api/ddocs/{ddocId}?apiKey=... until syncStatus is "synced" or "failed", then show the link if synced.
18
+
19
+ ## Server URL
20
+
21
+ If you fetched this document from a URL (e.g., http://localhost:8001/llm.txt):
22
+ - Your server URL is that URL without the /llm.txt suffix
23
+ - Example: http://localhost:8001/llm.txt → Server URL is http://localhost:8001
24
+
25
+ If this document was provided another way, ask the user for their server URL.
26
+
27
+ ## API Key Configuration
28
+
29
+ Before starting, check for stored credentials:
30
+
31
+ 1. Look for config file at: ~/.fileverseapirc
32
+ 2. If found with valid apiKey, use it automatically
33
+ 3. If not found or missing apiKey:
34
+ - Ask user for their Fileverse API key
35
+ - Offer to save it: "Would you like me to save this API key for future sessions?"
36
+ - If yes, create/update ~/.fileverseapirc with JSON: {"apiKey": "...", "serverUrl": "..."}
37
+
38
+ ## Connection Strategy
39
+
40
+ After getting the server URL:
41
+
42
+ 1. **Try API first**: Attempt GET {SERVER_URL}/ping
43
+ 2. **If successful** (response: {"reply":"pong"}) → Use API Mode
44
+ 3. **If connection fails** (timeout, refused, unreachable) → Switch to CLI Mode
45
+
46
+ In API mode, every request must include apiKey as a query parameter; the path is complete before any query string.
47
+
48
+ When switching to CLI mode, inform the user:
49
+ "I can't reach your server directly (localhost isn't accessible from here). I'll help you using CLI commands instead - just run them and share the output with me."
50
+
51
+ ---
52
+
53
+ # Quick reference
54
+
55
+ ## All API endpoints
56
+
57
+ | Method | Path | Auth | Key params/body |
58
+ |--------|------|------|-----------------|
59
+ | GET | /ping | No | - |
60
+ | GET | /api/ddocs | apiKey | limit, skip |
61
+ | GET | /api/ddocs/{ddocId} | apiKey | - |
62
+ | POST | /api/ddocs | apiKey | JSON: {title, content} or form-data: file |
63
+ | PUT | /api/ddocs/{ddocId} | apiKey | JSON: {title?, content?} or form-data: file |
64
+ | DELETE | /api/ddocs/{ddocId} | apiKey | - |
65
+ | GET | /api/folders | apiKey | limit, skip |
66
+ | POST | /api/folders | apiKey | body: see Create Folder |
67
+ | GET | /api/folders/{folderRef}/{folderId} | apiKey | - |
68
+ | GET | /api/search | apiKey | q (required), limit, skip |
69
+ | GET | /api/events/failed | apiKey | - |
70
+ | POST | /api/events/retry-failed | apiKey | - |
71
+ | POST | /api/events/{id}/retry | apiKey | - |
72
+
73
+ ## All ddctl commands
74
+
75
+ | Command | Purpose | Key options |
76
+ |---------|---------|-------------|
77
+ | ddctl list | List ddocs | -l/--limit, -s/--skip |
78
+ | ddctl get <ddocId> | Get document metadata | - |
79
+ | ddctl view <ddocId> | View content preview | -n/--lines (default 10) |
80
+ | ddctl create <filepath> | Create from file | title = filename; file cannot be empty |
81
+ | ddctl update <ddocId> | Update ddoc | -f/--file <path> or opens editor |
82
+ | ddctl download <ddocId> | Download to file | -o/--output <filename> |
83
+ | ddctl delete <ddocIds...> | Delete one or more | space-separated ids |
84
+ | ddctl events list-failed | List failed worker events | - |
85
+ | ddctl events retry <eventId> | Retry one failed event | - |
86
+ | ddctl events retry-all | Retry all failed events | - |
87
+
88
+ ---
89
+
90
+ # MCP Integration (Recommended for AI Agents)
91
+
92
+ The Fileverse API MCP server is the easiest way for AI agents to interact with Fileverse API. It wraps all API calls into native MCP tools with built-in sync polling.
93
+
94
+ ## Setup
95
+
96
+ Install Fileverse API globally, then configure your MCP client:
97
+
98
+ ### Claude Code / Cursor
99
+
100
+ Add to your MCP config (e.g., `.claude/mcp.json` or Cursor MCP settings):
101
+
102
+ ```json
103
+ {
104
+ "mcpServers": {
105
+ "fileverse-api": {
106
+ "command": "fileverse-api-mcp",
107
+ "env": {
108
+ "FILEVERSE_API_KEY": "your-api-key",
109
+ "FILEVERSE_SERVER_URL": "http://localhost:8001"
110
+ }
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ The MCP server can also read credentials from `~/.fileverseapirc` if env vars are not set.
117
+
118
+ ## Available MCP Tools
119
+
120
+ | Tool | Description |
121
+ |------|-------------|
122
+ | fileverse_list_documents | List documents with pagination |
123
+ | fileverse_get_document | Get a single document by ddocId |
124
+ | fileverse_create_document | Create document and wait for sync (returns link) |
125
+ | fileverse_update_document | Update document and wait for sync (returns link) |
126
+ | fileverse_delete_document | Delete a document |
127
+ | fileverse_search_documents | Search documents by text query |
128
+ | fileverse_get_sync_status | Check sync status and link of a document |
129
+ | fileverse_retry_failed_events | Retry all failed blockchain sync events |
130
+
131
+ Create and update tools automatically poll until blockchain sync completes, so the agent does not need to implement polling logic.
132
+
133
+ ---
134
+
135
+ # Response Schemas
136
+
137
+ ## Document
138
+
139
+ Fields returned by GET /api/ddocs/{ddocId} and in list/search results:
140
+
141
+ ```
142
+ {
143
+ ddocId: string, // Unique document identifier
144
+ title: string, // Document title
145
+ content: string, // Document content (text/markdown)
146
+ syncStatus: "pending" | "synced" | "failed",
147
+ link: string | null, // Public URL (only when syncStatus is "synced")
148
+ localVersion: number, // Increments on each local edit
149
+ onchainVersion: number, // Version published to blockchain
150
+ isDeleted: number, // 0 = active, 1 = deleted
151
+ onChainFileId: number | null,
152
+ portalAddress: string,
153
+ createdAt: string, // ISO timestamp
154
+ updatedAt: string // ISO timestamp
155
+ }
156
+ ```
157
+
158
+ ## Document List
159
+
160
+ Returned by GET /api/ddocs:
161
+
162
+ ```
163
+ {
164
+ ddocs: Document[],
165
+ total: number,
166
+ hasNext: boolean
167
+ }
168
+ ```
169
+
170
+ ## Search Result
171
+
172
+ Returned by GET /api/search:
173
+
174
+ ```
175
+ {
176
+ nodes: Document[], // Note: "nodes" not "ddocs"
177
+ total: number,
178
+ hasNext: boolean
179
+ }
180
+ ```
181
+
182
+ ## Create/Update Response
183
+
184
+ Returned by POST /api/ddocs and PUT /api/ddocs/{ddocId}:
185
+
186
+ ```
187
+ {
188
+ message: string,
189
+ data: Document // Extract ddocId from data.ddocId
190
+ }
191
+ ```
192
+
193
+ ## Event
194
+
195
+ Returned by GET /api/events/failed:
196
+
197
+ ```
198
+ {
199
+ _id: string,
200
+ type: "create" | "update" | "delete",
201
+ timestamp: number,
202
+ fileId: string,
203
+ portalAddress: string,
204
+ status: "pending" | "processing" | "processed" | "failed",
205
+ retryCount: number,
206
+ lastError: string | null,
207
+ userOpHash: string | null
208
+ }
209
+ ```
210
+
211
+ ---
212
+
213
+ # CLI MODE (Fallback when server unreachable)
214
+
215
+ Use this when you cannot reach the user's server (localhost, firewall, etc.).
216
+ You generate commands, user runs them and shares output with you.
217
+
218
+ ## Installation and invocation
219
+
220
+ To set up Fileverse API and run the server:
221
+
222
+ ```bash
223
+ npm install -g @fileverse/api
224
+ npx @fileverse/api --apiKey <key> --rpcUrl <url>
225
+ ```
226
+
227
+ The package exposes the ddctl binary. After npm install -g @fileverse/api, run ddctl <command>. Without global install: npx -p @fileverse/api ddctl <command>.
228
+
229
+ ## CLI Commands Reference
230
+
231
+ ### List Documents
232
+ ```bash
233
+ ddctl list
234
+ ddctl list -l 10 -s 20
235
+ ddctl list --limit 10 --skip 20
236
+ ```
237
+
238
+ ### Get Document Details
239
+ ```bash
240
+ ddctl get <ddocId>
241
+ ```
242
+ Shows metadata including the link (if synced to blockchain).
243
+
244
+ ### View Document Content
245
+ ```bash
246
+ ddctl view <ddocId>
247
+ ddctl view <ddocId> -n 20
248
+ ddctl view <ddocId> --lines 20
249
+ ```
250
+ Default preview is 10 lines.
251
+
252
+ ### Create Document
253
+ ```bash
254
+ ddctl create <filepath>
255
+ ```
256
+ Creates document from file. Title is derived from filename. File content cannot be empty.
257
+
258
+ ### Update Document
259
+ ```bash
260
+ ddctl update <ddocId> -f <filepath>
261
+ ddctl update <ddocId> --file <filepath>
262
+ ddctl update <ddocId>
263
+ ```
264
+ Without --file opens in editor (uses EDITOR env or vi).
265
+
266
+ ### Download Document
267
+ ```bash
268
+ ddctl download <ddocId>
269
+ ddctl download <ddocId> -o myfile.md
270
+ ddctl download <ddocId> --output myfile.md
271
+ ```
272
+ Output supports markdown.
273
+
274
+ ### Delete Document
275
+ ```bash
276
+ ddctl delete <ddocId>
277
+ ddctl delete <id1> <id2> <id3>
278
+ ```
279
+ One or more space-separated ddoc IDs.
280
+
281
+ ### Worker events
282
+ ```bash
283
+ ddctl events list-failed
284
+ ddctl events retry <eventId>
285
+ ddctl events retry-all
286
+ ```
287
+ If sync is stuck, run ddctl events list-failed then ddctl events retry <id> or ddctl events retry-all.
288
+
289
+ ## CLI Workflow Examples
290
+
291
+ ### Create and Check Sync Status
292
+ ```bash
293
+ ddctl create mydocument.md
294
+ ddctl get <ddocId>
295
+ ```
296
+ Repeat get until syncStatus is "synced"; then the link field shows the public URL.
297
+
298
+ ### Search and Update
299
+ ```bash
300
+ ddctl list
301
+ ddctl view <ddocId>
302
+ ddctl update <ddocId> --file updated.md
303
+ ddctl get <ddocId>
304
+ ```
305
+
306
+ ---
307
+
308
+ # API MODE (Primary - when server is reachable)
309
+
310
+ Use this when GET /ping succeeds. You make HTTP requests directly to the server.
311
+
312
+ ## Authentication & URL Construction
313
+
314
+ CRITICAL: The apiKey is a query parameter that goes at the END of the URL, after the complete path.
315
+
316
+ URL Structure: {SERVER_URL}{PATH}?apiKey={API_KEY}&{OTHER_PARAMS}
317
+
318
+ Step-by-step URL construction:
319
+ 1. Start with the server URL: http://localhost:8001
320
+ 2. Add the complete path: /api/ddocs/abc123
321
+ 3. Add ? and the apiKey: ?apiKey=your-key
322
+ 4. Add any other params with &: &limit=10
323
+
324
+ CORRECT examples:
325
+ - GET http://localhost:8001/api/ddocs?apiKey=xxx
326
+ - GET http://localhost:8001/api/ddocs/abc123?apiKey=xxx
327
+ - PUT http://localhost:8001/api/ddocs/abc123?apiKey=xxx
328
+ - GET http://localhost:8001/api/ddocs?apiKey=xxx&limit=10&skip=0
329
+
330
+ WRONG (do NOT do this):
331
+ - GET http://localhost:8001/api/ddocs?apiKey=xxx/abc123 ← WRONG: path after query param
332
+ - GET http://localhost:8001/api?apiKey=xxx/ddocs/abc123 ← WRONG: path after query param
333
+
334
+ The query string (?apiKey=...) must ALWAYS come after the full path is complete.
335
+
336
+ ## Common mistakes
337
+
338
+ - Putting path segments after ?apiKey=... (wrong).
339
+ - Forgetting that create/update return data.ddocId, not top-level ddocId; always use response.data.ddocId.
340
+ - Not polling after create/update until syncStatus is "synced" or "failed".
341
+
342
+ ## Important: Sync Status Polling
343
+
344
+ When you create or update a document, it syncs to blockchain asynchronously:
345
+
346
+ - **pending**: Saved locally, blockchain sync in progress
347
+ - **synced**: Published to blockchain (link field available)
348
+ - **failed**: Sync failed
349
+
350
+ After CREATE or UPDATE, poll until syncStatus is "synced" or "failed":
351
+
352
+ 1. POST /api/ddocs or PUT /api/ddocs/{id}
353
+ 2. Extract ddocId from response.data.ddocId (not from the top level)
354
+ 3. Poll: GET /api/ddocs/{ddocId}?apiKey={API_KEY}
355
+ 4. If "pending", wait 5 seconds and poll again
356
+ 5. If "synced": extract the "link" field and show as clickable: [View Document](link)
357
+ 6. If "failed", inform user of sync failure
358
+
359
+ Typical sync time: 5-30 seconds.
360
+
361
+ ## API Reference
362
+
363
+ Base: {SERVER_URL}
364
+
365
+ ### Health Check (No Auth)
366
+ GET /ping
367
+ Response: {"reply":"pong"}
368
+
369
+ ### List Documents
370
+ GET /api/ddocs?apiKey={API_KEY}&limit=10&skip=0
371
+
372
+ Response:
373
+ {
374
+ "ddocs": [...],
375
+ "total": 100,
376
+ "hasNext": true
377
+ }
378
+
379
+ ### Get Document
380
+ GET /api/ddocs/{ddocId}?apiKey={API_KEY}
381
+
382
+ Response:
383
+ {
384
+ "ddocId": "...",
385
+ "title": "...",
386
+ "content": "...",
387
+ "syncStatus": "pending|synced|failed",
388
+ "link": "https://...",
389
+ ...
390
+ }
391
+ (link available when synced)
392
+
393
+ ### Create Document (JSON - recommended for AI agents)
394
+ POST /api/ddocs?apiKey={API_KEY}
395
+ Content-Type: application/json
396
+
397
+ { "title": "Document Title", "content": "Document content here..." }
398
+
399
+ Response: 201 with { "message": "...", "data": { "ddocId": "...", "title": "...", "syncStatus": "...", ... } }
400
+ Extract ddocId from response.data.ddocId. Then poll GET /api/ddocs/{ddocId} until syncStatus is "synced", then show the link.
401
+
402
+ ### Create Document (Multipart - for file uploads)
403
+ POST /api/ddocs?apiKey={API_KEY}
404
+ Content-Type: multipart/form-data
405
+
406
+ Send a single form field "file" with the document file. Title is derived from the filename. Max file size 10MB.
407
+
408
+ Response: same as JSON create above.
409
+
410
+ ### Update Document (JSON - recommended for AI agents)
411
+ PUT /api/ddocs/{ddocId}?apiKey={API_KEY}
412
+ Content-Type: application/json
413
+
414
+ { "title": "New Title", "content": "Updated content..." }
415
+
416
+ Both fields are optional; send only what you want to change.
417
+
418
+ Response: 200 with { "message": "...", "data": { ... } }
419
+ Poll until synced, then show the link.
420
+
421
+ ### Update Document (Multipart - for file uploads)
422
+ PUT /api/ddocs/{ddocId}?apiKey={API_KEY}
423
+ Content-Type: multipart/form-data
424
+
425
+ Send a single form field "file" with the updated document file. Title is derived from the filename. Max file size 10MB.
426
+
427
+ Response: same as JSON update above.
428
+
429
+ ### Delete Document
430
+ DELETE /api/ddocs/{ddocId}?apiKey={API_KEY}
431
+
432
+ ### List Folders
433
+ GET /api/folders?apiKey={API_KEY}&limit=10&skip=0
434
+
435
+ Response:
436
+ {
437
+ "folders": [...],
438
+ "total": 100,
439
+ "hasNext": true
440
+ }
441
+
442
+ ### Create Folder
443
+ POST /api/folders?apiKey={API_KEY}
444
+ Content-Type: application/json
445
+
446
+ Required body fields: onchainFileId, folderId, folderRef, folderName, portalAddress, metadataIPFSHash, lastTransactionBlockNumber, lastTransactionBlockTimestamp.
447
+ Typically used for sync/on-chain integration, not ad-hoc folder creation by agents.
448
+
449
+ ### Get Folder
450
+ GET /api/folders/{folderRef}/{folderId}?apiKey={API_KEY}
451
+ Both folderRef and folderId are required.
452
+
453
+ ### Search Documents
454
+ GET /api/search?apiKey={API_KEY}&q={query}&limit=10&skip=0
455
+ Query parameter "q" is required.
456
+
457
+ Response:
458
+ {
459
+ "nodes": [...],
460
+ "total": 100,
461
+ "hasNext": true
462
+ }
463
+ (Search returns "nodes", not "ddocs".)
464
+
465
+ ### List Failed Events
466
+ GET /api/events/failed?apiKey={API_KEY}
467
+
468
+ Response: array of events (e.g. _id, fileId, portalAddress, type, timestamp, lastError).
469
+
470
+ ### Retry All Failed Events
471
+ POST /api/events/retry-failed?apiKey={API_KEY}
472
+
473
+ Response: { "retried": number }
474
+
475
+ ### Retry One Failed Event
476
+ POST /api/events/{id}/retry?apiKey={API_KEY}
477
+
478
+ Response: { "ok": true } or 404 if event not found or not in failed state.
479
+
480
+ ## OpenAPI Specification
481
+
482
+ A machine-readable OpenAPI 3.1 spec is available at GET {SERVER_URL}/openapi.json. Use it for auto-generating tool definitions or importing into Swagger UI / Postman.
483
+
484
+ ---
485
+
486
+ # Agent Workflow Recipes
487
+
488
+ ## Recipe 1: Publish a local file to blockchain
489
+
490
+ 1. Read the file content from the local filesystem
491
+ 2. POST /api/ddocs?apiKey={API_KEY} with JSON body: {"title": "<filename>", "content": "<file content>"}
492
+ 3. Extract ddocId from response.data.ddocId
493
+ 4. Poll GET /api/ddocs/{ddocId}?apiKey={API_KEY} every 5 seconds
494
+ 5. When syncStatus is "synced", show: "Published! [View Document](link)"
495
+ 6. If syncStatus is "failed", show: "Saved locally but blockchain sync failed. Run retry."
496
+
497
+ ## Recipe 2: Find and update a document by title
498
+
499
+ 1. GET /api/search?apiKey={API_KEY}&q={title} to search for the document
500
+ 2. From the results (response.nodes), find the matching document and extract its ddocId
501
+ 3. PUT /api/ddocs/{ddocId}?apiKey={API_KEY} with JSON body: {"content": "<new content>"}
502
+ 4. Poll GET /api/ddocs/{ddocId}?apiKey={API_KEY} until synced
503
+ 5. Show the updated link
504
+
505
+ ## Recipe 3: Check health and diagnose sync issues
506
+
507
+ 1. GET /ping - verify server is running (expect {"reply":"pong"})
508
+ 2. GET /api/ddocs?apiKey={API_KEY}&limit=5 - verify API key works and list recent docs
509
+ 3. GET /api/events/failed?apiKey={API_KEY} - check for failed sync events
510
+ 4. If failed events exist, POST /api/events/retry-failed?apiKey={API_KEY} to retry them
511
+ 5. Report: server status, number of documents, number of failed events (and if retried)
512
+
513
+ ---
514
+
515
+ # Claude Code Integration
516
+
517
+ ## Custom Slash Commands
518
+
519
+ You can create custom slash commands for Claude Code that integrate with Fileverse API. Create a `.claude/commands/` directory in your project and add markdown prompt files.
520
+
521
+ ### fileverse-publish.md
522
+
523
+ Create `.claude/commands/fileverse-publish.md`:
524
+
525
+ ```markdown
526
+ Publish a file to Fileverse API blockchain storage.
527
+
528
+ Steps:
529
+ 1. Read credentials from ~/.fileverseapirc (JSON with apiKey and serverUrl fields)
530
+ 2. Read the file at: $ARGUMENTS
531
+ 3. POST to {serverUrl}/api/ddocs?apiKey={apiKey} with JSON body:
532
+ Content-Type: application/json
533
+ {"title": "<filename without extension>", "content": "<file contents>"}
534
+ 4. Extract ddocId from response.data.ddocId
535
+ 5. Poll GET {serverUrl}/api/ddocs/{ddocId}?apiKey={apiKey} every 5 seconds until syncStatus is "synced" or "failed"
536
+ 6. If synced: show "Published! Link: {link}"
537
+ 7. If failed: show "Saved locally but blockchain sync failed"
538
+ ```
539
+
540
+ Usage: `/fileverse-publish path/to/document.md`
541
+
542
+ ### fileverse-list.md
543
+
544
+ Create `.claude/commands/fileverse-list.md`:
545
+
546
+ ```markdown
547
+ List all documents in Fileverse API.
548
+
549
+ Steps:
550
+ 1. Read credentials from ~/.fileverseapirc (JSON with apiKey and serverUrl fields)
551
+ 2. GET {serverUrl}/api/ddocs?apiKey={apiKey}&limit=50
552
+ 3. Display results as a table with columns: ddocId, title, syncStatus, link, updatedAt
553
+ 4. Show total count and whether more documents exist (hasNext)
554
+ ```
555
+
556
+ Usage: `/fileverse-list`
557
+
558
+ ### fileverse-search.md
559
+
560
+ Create `.claude/commands/fileverse-search.md`:
561
+
562
+ ```markdown
563
+ Search for documents in Fileverse API.
564
+
565
+ Steps:
566
+ 1. Read credentials from ~/.fileverseapirc (JSON with apiKey and serverUrl fields)
567
+ 2. GET {serverUrl}/api/search?apiKey={apiKey}&q=$ARGUMENTS
568
+ 3. Display matching documents with: ddocId, title, syncStatus, link
569
+ 4. Show total matches found
570
+ ```
571
+
572
+ Usage: `/fileverse-search meeting notes`
573
+
574
+ ### fileverse-status.md
575
+
576
+ Create `.claude/commands/fileverse-status.md`:
577
+
578
+ ```markdown
579
+ Check the sync status of a Fileverse API document.
580
+
581
+ Steps:
582
+ 1. Read credentials from ~/.fileverseapirc (JSON with apiKey and serverUrl fields)
583
+ 2. GET {serverUrl}/api/ddocs/$ARGUMENTS?apiKey={apiKey}
584
+ 3. Display:
585
+ - Title
586
+ - Sync Status (pending/synced/failed)
587
+ - Link (if synced)
588
+ - Local Version vs On-chain Version
589
+ - Last Updated
590
+ 4. If status is "failed", suggest running: POST {serverUrl}/api/events/retry-failed?apiKey={apiKey}
591
+ ```
592
+
593
+ Usage: `/fileverse-status <ddocId>`
594
+
595
+ ---
596
+
597
+ # Key Concepts
598
+
599
+ - **DDoc**: A document with unique ddocId
600
+ - **syncStatus**: pending → synced (success) or failed
601
+ - **link**: Public URL to view document (only available when synced)
602
+ - **localVersion**: Increments on each edit
603
+ - **onchainVersion**: Version on blockchain
604
+
605
+ # Error Handling
606
+
607
+ **400 Bad Request**: Validation errors (missing/invalid body or params). Response body: { "error": "..." } or { "message": "..." }.
608
+ **401 Unauthorized**: Invalid or missing API key
609
+ **404 Not Found**: Resource doesn't exist
610
+ **429 Too Many Requests**: If returned (e.g. from upstream), respect Retry-After header if present.
611
+ **500 Server Error**: Internal error, retry or inform user
612
+
613
+ ---
614
+
615
+ # Future Improvements (Planned)
616
+
617
+ - **SSE for Sync Status**: Real-time sync status push via GET /api/ddocs/:ddocId/stream to eliminate polling
618
+ - **Batch Operations**: POST /api/ddocs/bulk for creating/updating/deleting multiple documents at once
619
+ - **Partial Responses**: ?fields=ddocId,syncStatus,link for requesting only specific fields
620
+ - **TypeScript SDK**: Typed client library with built-in sync polling at @fileverse/api/client
621
+ - **Webhook Callbacks**: Register a URL to be notified when sync completes instead of polling