Skip to content

Commit bc63ca0

Browse files
committed
web: enable inbox && add inbox api docs
Signed-off-by: 01zulfi <[email protected]>
1 parent 61549e8 commit bc63ca0

File tree

7 files changed

+166
-3
lines changed

7 files changed

+166
-3
lines changed

apps/web/src/components/notebook/index.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import {
3131
Trash,
3232
Notebook as NotebookIcon,
3333
ArrowUp,
34-
Move
34+
Move,
35+
Copy
3536
} from "../icons";
3637
import { MenuItem } from "@notesnook/ui";
3738
import { hashNavigate, navigate } from "../../navigation";
@@ -41,6 +42,7 @@ import { useDragHandler } from "../../hooks/use-drag-handler";
4142
import { AddNotebookDialog } from "../../dialogs/add-notebook-dialog";
4243
import { useStore as useSelectionStore } from "../../stores/selection-store";
4344
import { store as appStore } from "../../stores/app-store";
45+
import { store as settingStore } from "../../stores/setting-store";
4446
import { Multiselect } from "../../common/multi-select";
4547
import { strings } from "@notesnook/intl";
4648
import { db } from "../../common/db";
@@ -51,6 +53,8 @@ import {
5153
import { useStore as useNotebookStore } from "../../stores/notebook-store";
5254
import { MoveNotebookDialog } from "../../dialogs/move-notebook-dialog";
5355
import { areFeaturesAvailable } from "@notesnook/common";
56+
import { showToast } from "../../utils/toast";
57+
import { writeToClipboard } from "../../utils/clipboard";
5458

5559
type NotebookProps = {
5660
item: NotebookType;
@@ -286,6 +290,24 @@ export const notebookMenuItems: (
286290
icon: Trash.path,
287291
onClick: () => Multiselect.moveNotebooksToTrash(ids),
288292
multiSelect: true
293+
},
294+
{
295+
type: "button",
296+
key: "copyid",
297+
title: "Copy ID",
298+
icon: Copy.path,
299+
onClick: async () => {
300+
try {
301+
await writeToClipboard({
302+
"text/plain": notebook.id
303+
});
304+
showToast("success", "Notebook ID copied to clipboard");
305+
} catch (e) {
306+
console.error(e);
307+
showToast("error", "Failed to copy Notebook ID");
308+
}
309+
},
310+
isHidden: !settingStore.get().isInboxEnabled
289311
}
290312
];
291313
};

apps/web/src/components/tag/index.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ import ListItem from "../list-item";
2121
import { navigate } from "../../navigation";
2222
import { Flex, Text } from "@theme-ui/components";
2323
import { store as appStore } from "../../stores/app-store";
24+
import { store as settingStore } from "../../stores/setting-store";
2425
import { db } from "../../common/db";
25-
import { Edit, Shortcut, DeleteForver, Tag as TagIcon } from "../icons";
26+
import { Edit, Shortcut, DeleteForver, Tag as TagIcon, Copy } from "../icons";
2627
import { MenuItem } from "@notesnook/ui";
2728
import { Tag as TagType } from "@notesnook/core";
2829
import { handleDrop } from "../../common/drop-handler";
@@ -36,6 +37,8 @@ import {
3637
withFeatureCheck
3738
} from "../../common";
3839
import { areFeaturesAvailable } from "@notesnook/common";
40+
import { showToast } from "../../utils/toast";
41+
import { writeToClipboard } from "../../utils/clipboard";
3942

4043
type TagProps = { item: TagType; totalNotes: number };
4144
function Tag(props: TagProps) {
@@ -160,6 +163,24 @@ export const tagMenuItems: (
160163
await Multiselect.deleteTags(ids);
161164
},
162165
multiSelect: true
166+
},
167+
{
168+
type: "button",
169+
key: "copyid",
170+
title: "Copy ID",
171+
icon: Copy.path,
172+
onClick: async () => {
173+
try {
174+
await writeToClipboard({
175+
"text/plain": tag.id
176+
});
177+
showToast("success", "Tag ID copied to clipboard");
178+
} catch (e) {
179+
console.error(e);
180+
showToast("error", "Failed to copy Tag ID");
181+
}
182+
},
183+
isHidden: !settingStore.get().isInboxEnabled
163184
}
164185
];
165186
};

apps/web/src/dialogs/settings/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const sectionGroups: SectionGroup[] = [
121121
key: "inbox",
122122
title: "Inbox",
123123
icon: Inbox,
124-
isHidden: () => true // hidden until complete
124+
isHidden: () => !useUserStore.getState().isLoggedIn
125125
}
126126
]
127127
},
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Inbox API
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: Inbox API
3+
description: Learn about Notesnook's Inbox API.
4+
---
5+
6+
# Inbox API
7+
8+
Notesnook's Inbox API allows a user to send data to their NN account from third party services. The inbox server exposes a public endpoint which accepts data, encrypts it, and adds it to the user's Notesnook account.
9+
10+
## When to use Inbox API
11+
12+
It is up to the user to decide when to use the Inbox API. Some common use-cases include:
13+
- Setting up a Zapier automation to send inbound emails to Notesnook as notes.
14+
- Integrating to a custom server.
15+
- Automating sending data from other apps to Noetesnook.
16+
17+
## How to use Inbox API
18+
19+
### 1. Enable Inbox API from settings.
20+
21+
# [Desktop/Web](#/tab/web)
22+
23+
`Settings > Inbox > Enable Inbox API`.
24+
25+
---
26+
27+
### 2. Get your Inbox API Key.
28+
29+
One API key should be created by default. You can create multiple API keys if needed.
30+
31+
# [Desktop/Web](#/tab/web)
32+
33+
`Settings > Inbox > Create Key`.
34+
35+
---
36+
37+
### 3. Post data to Inbox API endpoint.
38+
39+
**Endpoint**: `POST https://inbox.notesnook.com/`
40+
41+
#### Headers
42+
43+
| Header | Type | Status | Description |
44+
|--------|------|--------|-------------|
45+
| `Content-Type` | string | **Required** | Must be `application/json` |
46+
| `Authorization` | string | **Required** | Your inbox API key |
47+
48+
#### Request Body
49+
50+
| Field | Type | Status | Description |
51+
|-------|------|--------|-------------|
52+
| `title` | string | **Required** | Title. Minimum 1 character. |
53+
| `type` | string | **Required** | Entity type. Currently only `"note"` supported. |
54+
| `source` | string | **Required** | Source identifier (e.g., `"Zapier"`, `"Custom App"`). |
55+
| `version` | number | **Required** | Schema version. Currently `1`. |
56+
| `content` | object | Optional | Note content object |
57+
| `content.type` | string | **Required** (if content provided) | Content format. Currently only `"html"` supported. |
58+
| `content.data` | string | **Required** (if content provided) | HTML content as a string. |
59+
| `pinned` | boolean | Optional | Pin the note. Default: `false`. |
60+
| `favorite` | boolean | Optional | Mark as favorite. Default: `false`. |
61+
| `readonly` | boolean | Optional | Make note read-only. Default: `false`. |
62+
| `archived` | boolean | Optional | Archive the note. Default: `false`. |
63+
| `notebookIds` | string[] | Optional | Array of notebook IDs to assign note to. |
64+
| `tagIds` | string[] | Optional | Array of tag IDs to apply to note. |
65+
66+
#### Response
67+
68+
On success, the API returns a `200 OK` status.
69+
70+
On failure, appropriate HTTP status codes (4xx, 5xx) are returned with error details.
71+
72+
#### Example Request
73+
74+
```bash
75+
curl -X POST https://inbox.notesnook.com/ \
76+
-H "Content-Type: application/json" \
77+
-H "Authorization: <your-inbox-api-key-here>" \
78+
-d '{
79+
"title": "My Important Note",
80+
"type": "note",
81+
"source": "zapier-email-forwarding",
82+
"version": 1,
83+
"content": {
84+
"type": "html",
85+
"data": "<h1>Meeting Notes</h1><p>Discussed Q4 roadmap</p>"
86+
},
87+
"favorite": true,
88+
"tagIds": ["67aecf3b9e1398484554bc90"]
89+
}'
90+
```
91+
92+
> info
93+
>
94+
> Notebook and Tag IDs can be found by right-clicking on a notebook/tag and selecting `Copy ID`.
95+
96+
## How it works
97+
98+
Inbox uses a hybrid symmetric and asymmetric encryption (public/private key pairs) scheme to ensure all data is encrypted on the inbox server and decrypted on the user's clients (web or desktop, mobile isn't supported yet). The flow looks like this:
99+
100+
1. When user enables inbox from the settings:
101+
- The client generates a public/private encryption key pair. The public key is stored as-is on NN's servers. The private key is encrypted again with the user's encryption key and then stored on server.
102+
- User is also now able to generate API keys for the inbox endpoint. The API keys allow NN to authenticate the user for the inbox API.
103+
2. When user sends data to the inbox API:
104+
- The inbox endpoint is served from an inbox server separate from NN's servers. The data is encrypted using a random key. The random key itself is encrypted using the user's inbox public key. The entire payload is sent to the NN's servers where it is stored in the database.
105+
3. The inbox data is then synced to the web or desktop app. Using the private key, the data is decrypted on the client and then pushed into the user's database.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: Self-Hosting Inbox API
3+
description: Learn about self-hosting Notesnook's Inbox API.
4+
---
5+
6+
# Self-Hosting Inbox API
7+
8+
As you might've noticed, the incoming data the user sends to the inbox is unencrypted. Which is why the inbox API is served from a separate server. This allows us to self-host the inbox server without self-hosting the entire NN stack.
9+
10+
You can read how to self-host inbox server here: https://github.com/streetwriters/notesnook-sync-server/blob/master/Notesnook.Inbox.API/README.md

docs/help/docgen.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ navigation:
8080
- path: custom-themes/create-a-theme-with-theme-builder.md
8181
- path: custom-themes/install-a-theme-from-file.md
8282
- path: custom-themes/publish-a-theme.md
83+
- path: inbox-api
84+
children:
85+
- path: inbox-api/inbox-api.md
86+
- path: inbox-api/self-hosting-inbox-api.md
8387
- path: faqs
8488
children:
8589
- path: faqs/what-are-merge-conflicts.md

0 commit comments

Comments
 (0)