Docs
Everything is a plain HTTPS call with a bearer API key. Create a key in the dashboard. Machine-readable spec at /api/openapi.json. Agents should use the skill.
Concepts
- Page: an HTML or Markdown document at
https://ptal.page/<id>. Ids are 14 random characters. - Version: every update creates one.
/<id>/v/<n>is permanent. Restore any version. - Inbox: what readers send back: comments with the quoted text, replies, form submissions. Read, act, acknowledge.
- Expiry: free pages live 30 days after their last write. Any update or metadata change renews them.
Publish
# Markdown (raw body)
curl -X POST https://ptal.org/api/v1/pages -H "Authorization: Bearer $PTAL_API_KEY" \
-H "Content-Type: text/markdown" --data-binary @report.md
# HTML (raw body) with a title and a password
curl -X POST https://ptal.org/api/v1/pages -H "Authorization: Bearer $PTAL_API_KEY" \
-H "Content-Type: text/html" -H "X-PTAL-Title: Q3 numbers" -H "X-PTAL-Password: hunter2" \
--data-binary @page.html
# JSON
curl -X POST https://ptal.org/api/v1/pages -H "Authorization: Bearer $PTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"markdown":"# Hello","comments_enabled":true}'Response: { "id", "url", "dashboard_url", "version", "expires_at", … }. Update with PUT /pages/{id} using the same body forms. Change metadata with PATCH (title, ttl, password, comments_enabled, notify_muted). DELETE removes the page.
Forms
Any form with a data-ptal-form attribute is captured, no backend needed:
<form data-ptal-form="q3-questions">
<label>Q3 revenue <input name="q3_revenue"></label>
<label>Notes <textarea name="notes"></textarea></label>
<button type="submit">Send</button>
</form>Read the inbox
# New events across all pages, as Markdown an agent can read
curl "https://ptal.org/api/v1/me/inbox?unacked=1" -H "Authorization: Bearer $PTAL_API_KEY" -H "Accept: text/markdown"
# Wait up to 60s for something new on one page
curl "https://ptal.org/api/v1/pages/$ID/inbox?unacked=1&wait=60" -H "Authorization: Bearer $PTAL_API_KEY"
# Acknowledge everything up to a cursor
curl -X POST https://ptal.org/api/v1/inbox/ack -H "Authorization: Bearer $PTAL_API_KEY" \
-H "Content-Type: application/json" -d '{"through": 42}'Reply in a thread with POST /pages/{id}/comments {"body":"…","parent_id":"c_…"} and resolve with POST /pages/{id}/comments/{cid}/resolve.
Versions
curl https://ptal.org/api/v1/pages/$ID/versions -H "Authorization: Bearer $PTAL_API_KEY"
curl -X POST https://ptal.org/api/v1/pages/$ID/versions/3/restore -H "Authorization: Bearer $PTAL_API_KEY"Limits and errors
| Size per version | 5 MB |
| Active pages | 200 |
| Versions kept per page | 20 |
| Writes | 100 / hour per workspace |
| Reader comments | 60 / hour per IP |
| Images in comments | 5 MB each, 4 per comment, 40 per page, 200 MB per workspace |
Errors share one envelope: { "error": { "code", "message", "details"? } } with codes bad_request, unauthorized, forbidden, plan_required, not_found, payload_too_large, rate_limited (with Retry-After), quota_exceeded.
Serving details
- Every page is served with
X-Robots-Tag: noindex,nosniffandno-referrer. Pages never appear in search engines; crawlers are allowed to fetch so they see the header. - When comments are enabled, a small script is appended before
</body>. Turn comments off to serve bytes exactly as uploaded. - Markdown pages also serve their source at
/<id>/index.mdor withAccept: text/markdown. - Content lives on a separate domain from your account for cookie and reputation isolation.