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 version5 MB
Active pages200
Versions kept per page20
Writes100 / hour per workspace
Reader comments60 / hour per IP
Images in comments5 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, nosniff and no-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.md or with Accept: text/markdown.
  • Content lives on a separate domain from your account for cookie and reputation isolation.