ℹ️ Notes API and encryption

Encryption overview

Micro.blog on the web, the Strata mobile app, and the Mac app all use a basic JSON API to save and retrieve notes from the Micro.blog platform. By default, notes are encrypted in one of those clients before sending to the server, so Micro.blog never sees the note text. Shared notes are decrypted in the client so that Micro.blog has access to the text for publishing on your blog.

While we expect to support this API indefinitely, there will be additions in the future for better real-time syncing of notes. Currently, the clients just retrieve a list of recent notes when a view is refreshed, and Micro.blog assumes you are online.

Notes are encrypted and decrypted using AES-GCM with a 256-bit key. This key is generated by Micro.blog and the user is expected to save a copy. Micro.blog can also save it to iCloud private storage for a user signed in with their Apple ID. A prefix “mkey” is added to the key so it’s easy to differentiate from other keys.

As a reference for the basic logic, much of the code is available in the Strata open source project or in the JavaScript controller for Micro.blog on the web here.

JSON API

Most of the responses from the API are in JSON Feed format. The encrypted text is in the content_text field. For shared notes, content_text will be the plain text version and content_html will have the published text as HTML. Important special feeds are in _microblog.

All request should be sent to: https://micro.blog/

The following endpoints are supported:

  • GET /notes/notebooks — Get a list of notebooks.
  • GET /notes/notebooks/[id] — Get a list of notes for notebook ID.
  • GET /notes/[id] — Get a single note.
  • GET /notes/[id]/versions — Get saved revisions of a note. These are kept for 60 days.
  • POST /notes — Create a new note or save an existing note.
    • Form-encoded params:
      • notebook_id
      • id — Note ID if edited a note.
      • text — Encrypted unless shared.
      • is_encrypted — Should always be true unless shared.
      • is_sharing — Only if we are sharing this note for the first time.
      • is_unsharing — Only if un-sharing this note.
  • POST /notes/notebooks — Create a new notebook or save a notebook.
    • Form-encoded params:
      • id — Notebook ID if renaming a notebook.
      • name — Notebook name.
  • DELETE /notes/[id] — Delete a note by note ID.
  • DELETE /notes/notebooks/[id] — Delete a notebook by notebook ID.

Example response

Example of a JSON response from /notes/notebooks/1, showing special fields for Micro.blog. The first note is a shared note, so decrypted, and the second is a normal private note:

{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Micro.blog - Notes",
  "home_page_url": "https://micro.blog/",
  "feed_url": "https://micro.blog/notes/notebooks/1",
  "_microblog": {
    "about": "https://micro.blog/about/api",
    "notebook": {
      "id": 1,
      "name": "Notebook",
      "colors": {
        "light": "#fef9da",
        "dark": "#1f252e"
      }
    }
  },
  "items": [
    {
      "id": 123,
      "title": "",
      "content_text": "This is a test shared note.",
      "content_html": "<p>This is a test shared note.</p>",
      "url": "https://micro.blog/notes/90",
      "date_published": "2024-01-10T17:04:26.000+00:00",
      "date_modified": "2024-02-13T17:14:10.000+00:00",
      "_microblog": {
        "is_encrypted": false,
        "is_shared": true,
        "shared_url": "https://www.manton.org/notes/abcdefg…."
      }
    },
    {
      "id": 124,
      "title": "",
      "content_text": "ABCDEFGH...",
      "content_html": "",
      "url": "https://micro.blog/notes/161",
      "date_published": "2024-02-13T17:13:50.000+00:00",
      "date_modified": "2024-02-13T17:14:01.000+00:00",
      "_microblog": {
        "is_encrypted": true,
        "is_shared": false,
        "shared_url": ""
      }
    }
  ]
}

Security concerns or feedback? We welcome issues and suggestions to help@micro.blog.