Publish your first prototype with curl
Five commands, about five minutes. You publish an HTML file, get a link people can comment on, read their comments, ship a fix at the same link and close the thread. Everything here runs with a test key, so nothing touches your team's live documents or your plan.
1. Get a test key
Open https://app.ollav.app/keys, choose Test, keep the scopes upload, read and comment, and create the key. It is shown once.
export OLLAV_API_KEY=ol_test_...Check it works:
curl -s https://app.ollav.app/api/me -H "Authorization: Bearer $OLLAV_API_KEY"The response says "livemode": false: this key works in your own sandbox. Test documents carry a TEST mark and are deleted after 30 days, and a test key may make 60 requests a minute.
2. Publish a file
Any self-contained HTML file up to 15 MB works. No file handy? Make one:
cat > prototype.html <<'HTML'
<!DOCTYPE html>
<html><head><title>Pricing page</title></head>
<body><h1>Pricing</h1><p>Pro: €12 a month.</p><button id="buy">Buy now</button></body></html>
HTMLUpload it. curl reads the file from disk, which is also the cheapest way for an agent with a shell to publish:
curl -s -F "file=@prototype.html" \
-H "Authorization: Bearer $OLLAV_API_KEY" \
-H "X-Ollav-Client: agent" \
-H "Idempotency-Key: $(uuidgen)" \
https://app.ollav.app/api/documents{ "url": "https://content.ollav.app/p/qkjgjQCQGz", "slug": "qkjgjQCQGz", "versionId": "...", "deduped": false, "versioned": false, "warnings": [], "livemode": false }Open the url: that link is the deliverable. Keep the slug:
export SLUG=qkjgjQCQGzEvery POST, PATCH and DELETE needs X-Ollav-Client: agent. Idempotency-Key is optional: retry with the same key and the upload happens once.
3. Leave a comment
Normally a reviewer opens the link and clicks an element. To try the loop alone, pin one yourself:
curl -s -X POST https://app.ollav.app/api/comments \
-H "Authorization: Bearer $OLLAV_API_KEY" \
-H "X-Ollav-Client: agent" \
-H "Content-Type: application/json" \
-d "{\"slug\":\"$SLUG\",\"body\":\"Make the button say Start free trial\",\"selector\":\"#buy\",\"rect\":{\"x\":0,\"y\":0,\"w\":1,\"h\":1},\"elementText\":\"Buy now\"}"4. Read the feedback
/api/review returns the open threads. With format=markdown they come as a summary an agent can act on directly:
curl -s "https://app.ollav.app/api/review?slug=$SLUG&format=markdown" -H "Authorization: Bearer $OLLAV_API_KEY"Without format, the JSON has each thread's id, comment and anchor.quote (the element's text, for finding it in your source), plus a cursor: pass it as since next time to get only new activity.
Keep the first thread's id (this uses jq):
export COMMENT_ID=$(curl -s "https://app.ollav.app/api/review?slug=$SLUG" -H "Authorization: Bearer $OLLAV_API_KEY" | jq -r '.threads[0].id')5. Ship the fix at the same link, and resolve
Edit the file, then publish a new version. The URL stays the same and every comment is kept:
sed -i.bak 's/Buy now/Start free trial/' prototype.html
curl -s -F "file=@prototype.html" \
-H "Authorization: Bearer $OLLAV_API_KEY" \
-H "X-Ollav-Client: agent" \
https://app.ollav.app/api/documents/$SLUG/versionsClose the thread:
curl -s -X POST https://app.ollav.app/api/comments/$COMMENT_ID/resolve \
-H "Authorization: Bearer $OLLAV_API_KEY" \
-H "X-Ollav-Client: agent"When something fails
Errors are JSON with a stable code, a hint saying what to do and a doc_url. The common ones here:
| Code | Why | Fix |
|---|---|---|
AUTH_REQUIRED | The key is missing, mistyped or revoked | Check $OLLAV_API_KEY is exported in this shell |
CSRF_REQUIRED | A POST without X-Ollav-Client | Add -H "X-Ollav-Client: agent" |
NOT_FOUND | Wrong slug or id, or a live document with a test key | Use the slug from step 2 with the same key |
TOO_LARGE | Over 15 MB | Compress inlined images |
RATE_LIMITED | Over 60 requests a minute with a test key | Wait a minute |
Every code: errors.
Next
- Switch to a live key (
ol_live_...) to share with your team. Live documents count towards your plan. - Let your agent do this: Use Ollav from your agent via MCP.
- Every endpoint: REST API reference.