Sync API
Trove ingests content through the GraphQL API — there is no separate REST endpoint. A sync client (the Trove Mac app, or your own code) fetches content from an upstream and pushes it in. All requests go to https://api.ontrove.sh/graphql with an Authorization: Bearer <token> header.
The ingest flow
Section titled “The ingest flow”A document belongs to a feed, which belongs to a source. So a sync client:
- Ensures a source —
createSource(once per connected thing). - Ensures a feed within it —
addFeed(once per publication/stream; a single-feed source uses one feed withexternalKey: "default"). - Pushes documents —
ingestDocuments, passing both thesourceIdand thefeedId.
Steps 1–2 run once; subsequent syncs just call ingestDocuments.
Pushing documents
Section titled “Pushing documents”curl -X POST https://api.ontrove.sh/graphql \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "query": "mutation($sourceId: ID!, $feedId: ID!, $documents: [IngestDocumentInput!]!, $cursor: String) { ingestDocuments(sourceId: $sourceId, feedId: $feedId, documents: $documents, cursor: $cursor) { documentsIndexed documentsSkipped cursor errors { externalId message } } }", "variables": { "sourceId": "src_abc123", "feedId": "feed_def456", "cursor": "2026-03-25T12:00:00Z", "documents": [ { "externalId": "post-12345", "title": "Interesting Article", "text": "Full text content...", "url": "https://example.com/blog/post-12345", "author": "Jane Smith", "date": "2026-03-25T12:00:00Z", "contentType": "TEXT", "tags": ["tech", "ai"], "metadata": { "likes": 42 } } ] } }'Send up to 50 documents per call. See ingestDocuments for the full field reference and IngestDocumentInput for the document shape.
Cursor (incremental sync)
Section titled “Cursor (incremental sync)”cursor records where the feed’s sync left off. It’s stored on the feed and echoed back in the result; on the next run, read it from Feed.cursor to resume. Trove parses it into a FeedWatermark, so the app and tools can show “synced through <date>”. Pass cursorBefore (the value you last read) for compare-and-swap safety against concurrent syncs.
Deduplication
Section titled “Deduplication”Documents with the same (feedId, externalId) pair are skipped — re-submitting a batch never creates duplicates.
Audio (transcription)
Section titled “Audio (transcription)”To ingest audio, send a document with audioUrl instead of text. Trove transcribes it asynchronously using a speech-to-text model and indexes the resulting transcript with contentType: TRANSCRIPT.
Other operations
Section titled “Other operations”| Need | Use |
|---|---|
| Record a sync run for history | createSyncRun |
| List sources and their health | the sources query and stats |
| Delete a document | deleteDocument |