Sync API (REST)
The Sync API provides REST endpoints for data ingestion. The Trove desktop app and custom connectors use these to push data into your knowledge base.
All endpoints require an Authorization: Bearer <token> header.
Convention note: The Sync API uses snake_case for request fields (e.g.,
connector_id,external_id) and camelCase for response fields (e.g.,documentsIndexed). This differs from the GraphQL API, which uses camelCase throughout.
Base URL: https://api.ontrove.sh
POST /api/sync/documents
Section titled “POST /api/sync/documents”Batch ingest documents for a connector.
Request
Section titled “Request”curl -X POST https://api.ontrove.sh/api/sync/documents \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "connector_id": "abc123", "cursor": "optional-pagination-cursor", "documents": [ { "external_id": "post-12345", "title": "Interesting Article", "text": "Full text content of the article...", "url": "https://example.com/blog/post-12345", "author": "Jane Smith", "date": "2026-03-25T12:00:00Z", "content_type": "text", "tags": ["tech", "ai"], "metadata": { "likes": 42 } } ] }'Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
connector_id | string | Yes | The connector to ingest documents into. |
cursor | string | No | Pagination cursor for the connector’s sync state. |
documents | array | Yes | Array of documents. Minimum 1, maximum 50. |
Document Fields
Section titled “Document Fields”| Field | Type | Required | Description |
|---|---|---|---|
external_id | string | Yes | Unique identifier from the source system. Used for deduplication. |
title | string | No | Document title. |
text | string | Conditional | Full text content. Required unless audio_url is provided. |
audio_url | string | Conditional | URL to an audio file for transcription. Required if text is not provided. |
url | string | No | Source URL. |
author | string | No | Document author. |
date | string | No | ISO 8601 timestamp for the original publication date. |
content_type | string | No | Content type label. One of: "text", "transcript", "highlight", "bookmark". |
tags | string[] | No | Array of tags. |
metadata | object | No | Arbitrary key-value metadata. |
Deduplication
Section titled “Deduplication”Documents with the same (connector_id, external_id) pair are skipped. You can safely re-submit documents without creating duplicates.
Response (200)
Section titled “Response (200)”{ "documentsIndexed": 8, "documentsSkipped": 2, "errors": [ { "external_id": "id5", "error": "Document has no text" } ], "cursor": "next-cursor"}| Field | Type | Description |
|---|---|---|
documentsIndexed | number | Number of documents successfully indexed. |
documentsSkipped | number | Number of documents skipped (already exist). |
errors | array | Per-document errors. Empty array if all documents succeed. |
cursor | string | Updated cursor for the next batch. |
Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 | Missing connector_id, empty documents array, more than 50 documents, or missing external_id on a document. |
401 | Missing or invalid authorization token. |
404 | Connector not found. |
POST /api/sync/audio
Section titled “POST /api/sync/audio”Enqueue an audio file for transcription via Workers AI. The transcription is processed asynchronously. The resulting text is indexed as a document.
Request
Section titled “Request”curl -X POST https://api.ontrove.sh/api/sync/audio \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "connector_id": "abc123", "external_id": "episode-42", "audio_url": "https://example.com/episode.mp3", "title": "Episode 42: The Future of AI", "author": "Podcast Host", "date": "2026-03-25T12:00:00Z", "metadata": { "duration": 3600 } }'Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
connector_id | string | Yes | The connector this audio belongs to. |
external_id | string | Yes | Unique identifier from the source system. |
audio_url | string | Yes | URL to the audio file (MP3, WAV, etc.). |
title | string | No | Title for the transcribed document. |
author | string | No | Author or speaker. |
date | string | No | ISO 8601 timestamp. |
metadata | object | No | Arbitrary metadata (e.g., duration, episode number). |
Response (200)
Section titled “Response (200)”{ "status": "queued", "message": "Transcription workflow enqueued"}The audio is processed asynchronously by a Cloudflare Workflow. Once transcription completes, the resulting text is indexed as a document under the specified connector.
GET /api/sync/status
Section titled “GET /api/sync/status”Connector health overview. Returns a summary of all connectors and total document count.
Request
Section titled “Request”curl https://api.ontrove.sh/api/sync/status \ -H "Authorization: Bearer YOUR_TOKEN"Response (200)
Section titled “Response (200)”{ "connectors": [ { "id": "abc123", "connector_type": "rss", "name": "Tech Blogs", "status": "active", "document_count": 342, "last_synced_at": "2026-03-25T10:00:00Z" }, { "id": "def456", "connector_type": "hacker-news", "name": "Bookmarks", "status": "active", "document_count": 1158, "last_synced_at": "2026-03-25T09:30:00Z" } ], "total_documents": 1500}| Field | Type | Description |
|---|---|---|
connectors | array | Summary of each connector. |
connectors[].id | string | Connector ID. |
connectors[].connector_type | string | Connector type. |
connectors[].name | string | Connector display name. |
connectors[].status | string | Current status ("active", "paused", "error", "setup"). |
connectors[].document_count | number | Number of documents from this connector. |
connectors[].last_synced_at | string | ISO 8601 timestamp of the last successful sync. |
total_documents | number | Total documents across all connectors. |
DELETE /api/sync/documents/:id
Section titled “DELETE /api/sync/documents/:id”Delete a single document from all storage layers (D1, R2, Vectorize). This action is irreversible.
Request
Section titled “Request”curl -X DELETE https://api.ontrove.sh/api/sync/documents/doc_abc123 \ -H "Authorization: Bearer YOUR_TOKEN"Response (200)
Section titled “Response (200)”{ "deleted": true, "document_id": "doc_abc123"}Error (404)
Section titled “Error (404)”{ "error": "Document not found: doc_abc123"}