# PostMD — Service overview

PostMD stores markdown documents and serves them as web pages.

You upload a `.md` file. PostMD saves it and returns a short **document code**.
That code forms the document's viewer URL, and anyone who opens the URL sees the
rendered document.

The web app and the HTTP API do the same things. An agent holding an API key can
upload, read, update and delete documents on a member's behalf, exactly as a
person would in the browser. An MCP server (`npx -y postmd-mcp-server`) covers the same
ground for assistants that speak MCP.

## Core concepts

Read this section before using the API. Most integration mistakes come from
misreading one of these terms.

### Document

A single markdown file plus its settings (title, password, sharing period,
viewer theme).

Every document gets a **document code** such as `P-889-419-571`. The code is
assigned once at upload and never changes, so you can store it and use it later
to fetch, update or delete that document.

PostMD does not convert other formats. Only `.md` files are accepted.

### Group

A collection of documents that several people can see.

Every member account has one **default group**, created automatically at signup.
It cannot be deleted. Members can create additional groups.

**A document belongs to exactly one group.** It goes into the group you name at
upload. If you do not name one, it goes into your default group, so that every
document appears in a list. Moving it to another group replaces the group it was
in; the document itself, including its address, does not change.

### Group membership

A group has one **owner** — the account that created it — and any number of
**members**.

| Action | Owner | Member |
|---|---|---|
| Read documents in the group | yes | yes |
| Add documents to the group | yes | yes |
| Rename or delete the group | yes | no |
| Manage the invite link | yes | no |
| View or remove members | yes | no |

Members join through an **invite link**, described next. There is no way to add
someone to a group directly.

### Invite link

How a group accepts new members.

The owner turns the invite link on, which generates a link. Anyone who opens
that link and signs in becomes a member.

Three rules matter:

- **Turning the link off blocks new joins only.** Members who already joined
  stay in the group and keep their access.
- **Turning the link on again generates a different link.** The previous link
  stops working. Use this when a link has spread further than intended.
- **The default group cannot be shared this way.** It is where documents land
  when no group is named, so it collects work that was never meant for an
  audience. Create another group instead.

Invite links, joining and leaving are browser actions. An API key cannot perform
them.

### Note

Text a member attaches to a document while reading it, optionally anchored to a
quoted passage. A highlight is the same object carrying a colour and no text.

Every note has a visibility scope. `PRIVATE` notes are the author's reading
memos and stay invisible to everyone else. `SHARED` notes are comments: anyone
who can read the document sees them, and the document owner can resolve or
delete them. Documents without a personal owner — anonymous uploads and
service-owned pages — accept `PRIVATE` notes only, because no one could
moderate a public comment there.

Anchors are matched by the quoted text, not by position, so notes survive edits
elsewhere in the document. If the quoted passage itself disappears, the note
keeps its text and loses only its place in the body.

Highlight colours are four fixed codes. Each member may name them for
themselves (for example "needs review"); the colour travels with a shared note,
the name never leaves the member who set it.

### API key

The credential an agent uses to call the API. It always starts with `pmk_`.

A member issues API keys from the web app. At issue time they choose:

- **Scopes** — which operations the key may perform.
- **An expiry date** — required, and at most one year away.

The key itself is shown **once**, in the response to the issue request. PostMD
stores only a hash of it and cannot show it again. If it is lost, revoke the key
and issue a new one.

### Scope

A permission attached to an API key.

| Scope | Allows |
|---|---|
| `documents:read` | Reading documents |
| `documents:write` | Uploading, updating and deleting documents |
| `groups:read` | Reading groups |
| `groups:write` | Creating, updating and deleting groups |

**Read and write are separate permissions.** Holding `documents:write` does not
allow reading documents. If your integration both uploads and reads back, grant
both scopes.

## Sharing and access

A document's viewer URL works for anyone who has it. There is no "publish" step.

Two settings restrict that:

- **Password** — the reader must supply it before the content is returned.
- **Sharing end date** — after this date the document stops being served.

The owner is never blocked by either setting.

Documents inside a group are a separate matter: only the group's owner and its
members can list them.

## Behaviour worth knowing

### Images and relative paths

A markdown file that references an image by relative path — for example
`![diagram](../images/a.png)` — will show a broken image after upload. PostMD
stores only the markdown file, not the folder it came from.

Upload each image through the attachment endpoint first. It returns a URL.
Replace the relative path in your markdown with that URL, then upload the
markdown.

### Deletion

Deleting a document or a group takes effect immediately: it disappears from
listings and its URL stops working.

There is **no endpoint to restore it**, so treat deletion as permanent. The
stored content of a deleted document is removed from the server about a month
later.

### Unused uploads

An image you upload but never reference from a document is removed after about
a week. Upload images shortly before you upload the document that uses them.

### Anonymous upload

A request with no credential can still upload a document. Ownership is assigned
to an internal system account.

Nobody can update or delete such a document afterwards, because no account owns
it. Use a credential if you need to manage the document later.

### Encryption at rest

Document content and uploaded attachments are encrypted before they are written
to disk, and decrypted when served. This changes nothing for API clients — you
send and receive plain markdown and plain files.

Files uploaded before this was introduced remain stored as they were and are
still served correctly.

**An attachment URL is a bearer address**, like a document code: anyone holding
it can fetch the file. A document password gates the markdown body, not the
files it references.

### Account withdrawal

When a member withdraws, the account and its documents are kept for one month.
After that the documents are deleted and personal data is masked.

During that month the account can sign in but cannot use ordinary features.

## Documents

- [API reference](/docs/api) — endpoints, authentication, error codes.
- [Changelog](/docs/changelog) — what changed and when.
- [OpenAPI spec](/api-docs) — machine-readable API description.

## Service

<https://postmd.turink.com>
