# Concepts

DocPin comes down to a handful of objects, three ways a page changes, and one way pages are served. Read this first: the rest of the docs build on it.

## The objects

```diagram model
caption: A workspace holds pages, optionally grouped in boards. Each page has its HTML versions, its data and its entries, plus who can open it and its links.
Workspace ─holds─▶ Board (optional) ─groups─▶ Page ─┬─▶ Versions   the HTML you publish
                                                   ├─▶ Data       JSON you push
                                                   └─▶ Entries    what viewers save
                                    every page also has: access · links
```

| Concept | What it is | Example |
| --- | --- | --- |
| **Workspace** | Your pages, boards, members, branding and domain. An API key belongs to one workspace; an AI-app connection can use every workspace you can publish to. | `acme` → `acme.docpin.it` |
| **Board** | An optional group of pages, with its own landing page and access setting. | `/launch` |
| **Page** | One published thing at one address. Identified by its `id`, or by its `slug` plus its board. | `/launch/plan` |
| **Version** | One publish of a page's HTML and files. Publishing the same slug again adds a version behind the same link. | Version 3 of `/launch/plan` |
| **Page data** | One JSON object per page that **you** write and the page reads. | `{ "revenue": 128400 }` |
| **Entries** | What **viewers** save from a page: votes, RSVPs, answers, comments. Off until turned on. | Sam's RSVP |
| **Access** | Who can open a page or board. | `team`, `public`, `password`, `people` |
| **Member** | Someone in the workspace. Members manage pages; viewers just open them. | |

## Three ways a page changes

| | HTML (versions) | Page data | Entries |
| --- | --- | --- | --- |
| **Written by** | You, by publishing | You, from the API, MCP or the app | Viewers, from the page |
| **Write with** | `POST /v1/pages`, `publish_page`, an upload | `PATCH /v1/pages/{id}/data`, `set_page_data` | `docpin.shared.put` / `add`, `docpin.mine.set` |
| **The page reads it with** | (it is the page) | `docpin.data()` | `docpin.shared.list()`, `docpin.mine.get()` |
| **Adds a version** | Yes | No | No |
| **Who can see it** | Anyone who can open the page | Anyone who can open the page | Shared entries: anyone who can open the page, with names only. Private objects: only their author. Your workspace sees everything, with emails |
| **Size** | 25 MB per upload | 1 MB | 1 MB (Free) or 10 MB (Pro) per page |
| **Docs** | [REST API](/docs/api.md#publish) | [Page data](/docs/page-data.md) | [Entries](/docs/entries.md) |

## How a page is served

```diagram serving
caption: Your HTML runs in a sandboxed frame inside the DocPin page at your link. It reads page data directly; entries go through the DocPin page, which adds the viewer's sign-in.
Visitor ──link──▶ DocPin page   at your link: checks access, shows the pill
                  └─ Your HTML  sandboxed frame on docpinusercontent.com, no cookies, docpin.* added first
                       ├─ docpin.data() ─────────────────────────────────────▶ Page data
                       └─ docpin.shared.* ─postMessage─▶ DocPin page ─sign-in─▶ Entries
```

1. A visitor opens a link. The **DocPin page** answers it: it checks access (password or sign-in) and shows the DocPin pill.
2. Your HTML loads in a **sandboxed frame** on its own origin. It can't read the DocPin page, its cookies or the visitor's sign-in.
3. Before your scripts run, DocPin adds the global **`docpin`** object, syncing of `?query` and `#hash`, and a working `localStorage`.
4. `docpin.data()` reads page data straight from the frame's origin. Entries calls go to the DocPin page, which adds who's signed in.

The whole environment, with what works and what's blocked: [How pages run](/docs/page-runtime.md).

## Access

| `kind` | Who can open it | Plan |
| --- | --- | --- |
| `team` | Members of the workspace, signed in | Free |
| `public` | Anyone with the link | Free |
| `password` | Members, plus anyone with the password | Pro |
| `people` | Members, plus listed emails or `@domains`, once they confirm their email | Pro |
| `inherit` | Pages only: follows its board, or a top-level page takes the workspace's default | Free |

Pages in a board follow the board unless they set their own access. New top-level pages follow the workspace's **New pages start as** setting ([`GET /v1/defaults`](/docs/api.md#get-v1-defaults)).

## Page lifecycle

```diagram lifecycle
caption: A page is a draft or live. Publishing the same slug again adds a version behind the same link, and brings an archived page back.
Draft   (only its author, no link) ──share──▶ Live (at its link) ──archive──▶ Archived (off the page list, link works)
        ◀──make draft──                                          ◀──unarchive──
Live or Archived ──publish the same slug again──▶ Live: new version, same link
```

| State | Who can open it | Link | Takes entries |
| --- | --- | --- | --- |
| **Draft** | Only the person who made it | None; a preview link lasts an hour | No |
| **Live** | Whoever its access allows | Works | If turned on |
| **Archived** | Whoever its access allows | Works; hidden from the home page, board pages and the app's page list | No |
| **Deleted** | Nobody | Stops working. Versions, data and entries are deleted | No |

Whether a new page starts as a draft or goes live is the workspace's **New pages start as** setting. `draft: true` or `draft: false` on publish overrides it. Making a page a draft again takes it out of its board and clears its access, so sharing it sets access afresh.

## Addresses

| Address | Example | Notes |
| --- | --- | --- |
| Workspace link | `https://acme.docpin.it/sales` | `{workspace}.docpin.it/{slug}`, or `/{board}/{slug}` in a board |
| Custom domain | `https://docs.acme.com/sales` | Pro. Becomes the main link; the workspace link still works |
| Short link | `https://docpin.it/Ab3dE7` | Never changes. The only link for unlisted pages. Case-sensitive |
| REST API | `https://api.docpin.app` | [REST API](/docs/api.md) |
| MCP server | `https://mcp.docpin.app/mcp` | [MCP](/docs/mcp.md) |

## Plans

| | Free | Pro ($8 a month) |
| --- | --- | --- |
| Pages | 3 (archived ones count), plus up to 20 drafts each | Unlimited |
| Storage | 250 MB across all versions | Unlimited |
| Access | `team`, `public`, secret links | Adds `password` and `people` |
| Custom domain | | Yes |
| Page data and entries | Yes | Yes, with higher entry limits |
| Branding | A logo | Adds a tab icon, a share image, and clean or custom templates |
| Teammates | 1 | More |
