Examples
Each example needs an API key. They read it from an environment variable, so it never ends up in your code:
export TROVEMARKS_KEY=tm_…
Save a link from the terminal
A tiny shell function. Put it in your ~/.zshrc or ~/.bashrc, then run save https://example.com/article reading.
save() {
url="$1"; shift
tags=$(printf '"%s",' "$@"); tags="[${tags%,}]"
curl -s https://trovemarks.com/api/v1/bookmarks \
-H "Authorization: Bearer $TROVEMARKS_KEY" \
-H "Content-Type: application/json" \
-d "{\"url\": \"$url\", \"tags\": $tags}" | jq -r '.bookmark.title'
}
Turn a collection into a newsletter section
Many curators collect links all week, then write them up. This script prints the last week’s links from one collection as Markdown, with your notes, ready to paste into your newsletter.
// weekly.mjs: node weekly.mjs "Weekly picks"
const API = 'https://trovemarks.com/api/v1'
const headers = { Authorization: `Bearer ${process.env.TROVEMARKS_KEY}` }
const get = async (path) => {
const res = await fetch(`${API}${path}`, { headers })
if (!res.ok) throw new Error((await res.json()).error.message)
return res.json()
}
const name = process.argv[2] ?? 'Weekly picks'
const { data: collections } = await get('/collections?limit=500')
const collection = collections.find((c) => c.title.toLowerCase() === name.toLowerCase())
if (!collection) throw new Error(`No collection called ${name}`)
const since = new Date(Date.now() - 7 * 864e5).toISOString()
let cursor = ''
const links = []
do {
const page = await get(
`/bookmarks?collection=${collection.id}&saved_after=${since}&limit=100${cursor && `&cursor=${cursor}`}`,
)
links.push(...page.data)
cursor = page.next_cursor
} while (cursor)
for (const link of links.reverse()) {
console.log(`- [${link.title}](${link.url})${link.note ? ` — ${link.note}` : ''}`)
}
Prefer not to write code? Every public collection has an RSS feed, and most newsletter tools can turn a feed into a section of your email.
Save a list of links
Save every link in a text file, one per line, into a collection. Python, with nothing to install:
# save_all.py: python3 save_all.py links.txt "Research"
import json, os, sys, time, urllib.request
API = "https://trovemarks.com/api/v1/bookmarks"
KEY = os.environ["TROVEMARKS_KEY"]
path, collection = sys.argv[1], sys.argv[2]
for line in open(path):
url = line.strip()
if not url:
continue
body = json.dumps({"url": url, "collection_names": [collection]}).encode()
request = urllib.request.Request(API, data=body, headers={
"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json",
})
with urllib.request.urlopen(request) as response:
print(response.status, url) # 201 saved, 200 already there
time.sleep(0.25) # well inside the rate limit
For thousands of links, an import file is faster.
Tidy up many links at once
One request can change up to 10,000 links that match a filter. This makes every link from one site public:
curl https://trovemarks.com/api/v1/bookmarks/bulk \
-H "Authorization: Bearer $TROVEMARKS_KEY" \
-H "Content-Type: application/json" \
-d '{"filter": {"domain": "example.com"}, "action": {"type": "visibility", "private": false}}'
Check what a filter matches first with POST /bookmarks/bulk/summary, which takes the same body without action.
Zapier, Make and n8n
Use their HTTP or webhook step to call the API. For example, to save every link you star in your feed reader, or every link posted in a Slack channel:
| Field | Value |
|---|---|
| Method | POST |
| URL | https://trovemarks.com/api/v1/bookmarks |
| Headers | Authorization: Bearer tm_… and Content-Type: application/json |
| Body | {"url": "<the link from the trigger>", "tags": ["slack"]} |
To go the other way, from Trovemarks into another tool, use a public collection’s RSS feed as the trigger.
Apple Shortcuts
The iPhone shortcut is a good starting point for your own: it’s a single Get Contents of URL action that posts to /api/v1/bookmarks with your key. Duplicate it and change the body to add tags, a collection or a note.