Markdown Documents
Markdown document hosting (v0.15.0) lets you upload .md files to Picora and get a permanent URL for each. The killer feature: automatic embedded base64 image rewriting — Picora extracts inline images, uploads them as separate files, and replaces the URLs in your markdown.
Combined with MCP integration, this is how AI tools like Claude / Cursor publish your notes to a stable cloud URL with one prompt.
Quick upload via dashboard
- Open Library → Documents
- Drag a
.mdfile or click Upload / Paste text - Wait for the upload + image rewriting (typically <8 seconds for documents with up to 50 images)
- Online viewer opens automatically; copy the share link
Upload via API
curl -X POST https://api.picora.me/v1/docs \ -H "Authorization: Bearer sk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "filename": "release-notes.md", "content": "# v0.15 Release\n\n\n\nFirst paragraph...", "title": "v0.15 Release Notes", "tags": ["release", "v0.15"], "isPublic": false, "rewriteImages": true }'Response:
{ "success": true, "data": { "id": "doc_xK9mR2pQ7vBnE3wF8sCd2", "title": "v0.15 Release Notes", "filename": "release-notes.md", "sizeBytes": 4523, "wordCount": 312, "imageCount": 1, "rewrittenCount": 1, "failedCount": 0, "isPublic": false, "tags": ["release", "v0.15"], "createdAt": "2026-04-27T08:00:00Z" }}Embedded image rewriting {#rewriting}
Picora parses your markdown using a proper AST (not regex) and handles four embedded image syntaxes:
 # inline base64 — REWRITTEN![alt][ref] # reference style — REWRITTEN[ref]: data:image/png;base64,iVBORw...<img src="data:image/png;base64,iVBORw..." /> # HTML inline — REWRITTEN # already on Picora — KEPT # third-party — KEPT # local file — SKIPPED with warningWhat gets rewritten: only data:image/...;base64, URIs are decoded and re-uploaded. Third-party URLs are not transferred (legal gray area; we respect original sources).
Where rewritten images go: into your image storage quota as regular images. They appear in your Library Images tab with a tag indicating they came from a markdown document.
CDN allowlist: Picora maintains an admin-configured allowlist of trusted CDN domains. URLs matching the allowlist are recognized as “already on Picora” and skipped. The default allowlist includes media.picora.me / *.picora.me / *.picora.cn. See admin / CDN allowlist for details.
Per-plan limits
| Tier | doc count | max file | max embedded images |
|---|---|---|---|
| trial | 100 | 1 MB | 30 |
| pro | 1,000 | 5 MB | 100 |
| pro_plus | 10,000 | 5 MB | 300 |
If embedding images exceeds your image storage quota, the entire document upload fails (QUOTA_EXCEEDED: img_storage) and any successfully uploaded images are rolled back (best-effort).
Failure handling
If individual images fail to decode or upload (e.g., corrupted base64, R2 timeout), the document still saves — the failed images keep their original data: URLs in the rewritten markdown. The response’s failures[] array tells you which indices failed.
This means you’ll never lose a document due to a single bad image; you can retry / fix later.
Online viewer
Each document has a viewer at https://center.picora.me/library/docs/{id}:
- Markdown rendered with
react-markdown+ GFM (tables, task lists, strikethrough, autolinks) - Code blocks: syntax highlighting (12 common languages, lazy-loaded)
- Math: LaTeX with KaTeX (lazy-loaded when the doc contains
$$) - Diagrams: Mermaid (lazy-loaded when the doc contains
```mermaid) - Lazy-loaded inline images via
<img loading="lazy"> - Floating TOC for documents with H1-H3 (only shown when the doc is over 1500 words)
- Copy toolbar: copy raw URL / copy markdown source / download
.md/ show QR code (for public docs)
Visibility
- Private (default): only you can view;
/rawendpoint requires authentication - Public: anyone with the URL can view;
/rawis freely fetchable
This is the opposite default from images — markdown documents are typically private notes.
Source hash & idempotency
Picora computes SHA-256 of the rewritten markdown. If you upload the same content twice (same hash, same user), the second upload returns 409 DOC_HASH_DUPLICATE with the existing document’s ID. It does not consume your document quota for duplicates.
This is useful for AI tools that may retry uploads — they get back the original ID without creating duplicates.
Updating a document
There’s currently no PATCH-content endpoint. To update a document:
- Delete the old document
- Upload the new content (will get a new ID and new URL)
Cloud editor with proper update / version history is on the v0.20+ roadmap.
You can PATCH metadata only:
curl -X PATCH https://api.picora.me/v1/docs/{id} \ -H "Authorization: Bearer sk_live_..." \ -H "Content-Type: application/json" \ -d '{"title": "New title", "isPublic": true, "tags": ["updated"]}'Deletion
Same as other resource types — DELETE endpoint or dashboard. Deleting a document does not delete the embedded images that were rewritten (they may be referenced from other documents). Orphan image cleanup is on the v0.20+ roadmap.
Common issues
“22 errors during upload — file:// links skipped” — your markdown referenced local files. Replace them with inline base64 or third-party URLs before uploading.
“403 QUOTA_EXCEEDED: img_storage during upload” — embedded images would exceed your image quota. Free up image storage or upload the document with rewriteImages=false (images stay as-is in the markdown).
“422 DOC_FILE_TOO_LARGE” — your .md file exceeds your plan’s doc_max_file_bytes. Split into multiple documents or upgrade.
“Mermaid / KaTeX not rendering” — make sure you’re viewing the document in Picora’s online viewer (the /library/docs/{id} page), not just the raw markdown. The viewer auto-loads these libraries.
Related
- API Reference — Documents
- AI Workflows — Tool catalog —
upload_docMCP tool - Quota overview — doc count and image side-effects
- CDN allowlist (admin)