Roam Research Docs · Developer documentation
window object as window.roamAlphaAPI and is available from roam/js/roam/cljs code blocks, Roam Depot extensions, roam/render, and the browser console.
.catch(), or try/catch with await.
q, pull, pull_many and their variants time out after 20 seconds, throwing Query and/or pull expression took too long to run.
roamAlphaAPI.util.generateUID.
MM-DD-YYYY format (e.g. 07-16-2026 for July 16th, 2026) — see roamAlphaAPI.util.dateToPageUid.
roamAlphaAPI.apiVersion (string) — the API version, e.g. "1.1.3"; use it for feature detection
roamAlphaAPI.data
roamAlphaAPI.data.q
roamAlphaAPI.q (older top-level name; prefer this namespaced path)
:timeout <ms> clause in the query to override.
% in the :in clause; rules can be recursive.
count, contains?, get, ...), string helpers (str, subs, clojure.string/includes?/starts-with?/ends-with?/blank?), and regex (re-find, re-matches, re-seq, re-pattern). Custom functions can't be resolved from JS query strings.
query (string, required) — the datalog query
...args (optional) — additional inputs, bound to the query's :in clauses (the database itself is passed implicitly)
// all block uids and strings in the graph
window.roamAlphaAPI.data.q(
`[:find ?b ?s
:where
[?e :block/uid ?b]
[?e :block/string ?s]]`);
// => [["y3LFc4rFd", "some block text"], ["09sbCUlgt", "another block"], ...]
// with an :in argument
window.roamAlphaAPI.data.q(
`[:find ?s
:in $ ?uid
:where
[?e :block/uid ?uid]
[?e :block/string ?s]]`,
"abc123xyz");
// => [["the block's text"]]
roamAlphaAPI.data.pull
roamAlphaAPI.pull (older top-level name; prefer this namespaced path)
pattern (string, required) — pull pattern, e.g. "[*]" or "[:block/string {:block/children ...}]"
eid (required) — one of:
:db/id integer, e.g. 24
"[:node/title \"hello world\"]"
[":block/uid", "xyz"]
opts (object, optional) — {timeout: <ms>} overrides the default 20-second timeout
// all attributes of this block
window.roamAlphaAPI.data.pull("[*]", [":block/uid", "xyz"])
// =>
{":block/uid": "xyz",
":block/string": "the block's text",
":block/order": 0,
":block/open": true,
":create/time": 1610031973159,
":edit/time": 1610031974560,
":block/children": [{":db/id": 1234}],
":db/id": 1041}
// this block's string and all of its descendants
window.roamAlphaAPI.data.pull("[:block/string {:block/children ...}]", "[:block/uid \"xyz\"]")
// =>
{":block/string": "the block's text",
":block/children": [{":block/string": "child text"}]}
roamAlphaAPI.data.pull_many
roamAlphaAPI.data.pull, but for many entities at once — faster than pulling in a loop. Synchronous.
pattern (string, required) — same as roamAlphaAPI.data.pull's pattern
eids (array, required) — array of eids, each in any of the forms roamAlphaAPI.data.pull's eid accepts
opts (object, optional) — {timeout: <ms>} overrides the default 20-second timeout
roamAlphaAPI.data.pull_many("[*]",
[[":block/uid", "_fM7pkQEa"], [":block/uid", "kZHsZniZs"]]);
// =>
[{":block/uid": "_fM7pkQEa",
":block/string": "first block",
...},
{":block/uid": "kZHsZniZs",
":block/string": "second block",
...}]
roamAlphaAPI.data.fast.q
roamAlphaAPI.data.q, using an experimental clojurescript→javascript conversion that makes read access roughly 33% faster.
obj[":block/string"]. If you rename a key in the pull ([:block/string :as "string"]), access it as obj.string.
window.roamAlphaAPI.data.fast.q(
`[:find ?b ?s
:where
[?e :block/uid ?b]
[?e :block/string ?s]]`);
// => proxy-wrapped results — index like a regular array, treat as read only
roamAlphaAPI.data.backend.q
roamAlphaAPI.data.q, but runs the query on the backend, off the main thread — useful for expensive queries.
await window.roamAlphaAPI.data.backend.q(
`[:find ?b ?s
:where
[?e :block/uid ?b]
[?e :block/string ?s]]`);
// => [["y3LFc4rFd", "some block text"], ...]
roamAlphaAPI.data.async
q, pull, pull_many, search, fast.q); semanticSearch is async-only.
roamAlphaAPI.data.async.q
roamAlphaAPI.data.q. Same 20-second timeout, overridable with a :timeout clause in the query.
roamAlphaAPI.data.q
await roamAlphaAPI.data.async.q(
`[:find ?s
:in $ ?uid
:where
[?e :block/uid ?uid]
[?e :block/string ?s]]`,
"abc123xyz")
// => [["the block's text"]]
roamAlphaAPI.data.async.pull
roamAlphaAPI.data.pull.
roamAlphaAPI.data.pull
await roamAlphaAPI.data.async.pull("[*]", [":block/uid", "xyz"], {timeout: 60000})
// => {":block/uid": "xyz", ":block/string": "the block's text", ...}
roamAlphaAPI.data.async.pull_many
roamAlphaAPI.data.pull_many.
roamAlphaAPI.data.pull_many
await roamAlphaAPI.data.async.pull_many("[*]",
[[":block/uid", "_fM7pkQEa"], [":block/uid", "kZHsZniZs"]], {timeout: 60000})
// => [{":block/uid": "_fM7pkQEa", ...}, {":block/uid": "kZHsZniZs", ...}]
roamAlphaAPI.data.async.search
roamAlphaAPI.data.search. Uses the search worker when available, transparently falling back to the standard search — same parameters and return shape.
roamAlphaAPI.data.search
await roamAlphaAPI.data.async.search({"search-str": "my query", limit: 50})
// => [{":node/title": "My Query Notes", ":block/uid": "aBc123xYz"}, ...]
roamAlphaAPI.data.async.semanticSearch
roamAlphaAPI.data.semanticSearchEnabled first. While embeddings are still indexing, it returns partial results rather than throwing.
search-str (string, required) — the search query (search-string is accepted as an alias)
k (number, optional, default 25, max 200) — number of results (also the search pool size)
search-blocks (boolean, optional, default true) — include block results
search-pages (boolean, optional, default true) — include page results
hide-code-blocks (boolean, optional, default: the user's hide-code-blocks setting) — exclude code blocks
{type, uid, topUids}:
type — "chunk", "block", or "page"
uid — the hit's primary block uid (the first of topUids)
topUids — the hit's top-level block uids
await roamAlphaAPI.data.async.semanticSearch({"search-str": "my query"})
// =>
[{type: "chunk",
uid: "aBc123xYz",
topUids: ["aBc123xYz", "dEf456uVw"]},
{type: "page",
uid: "gHi789jKl",
topUids: ["gHi789jKl"]},
...]
roamAlphaAPI.data.async.fast.q
roamAlphaAPI.data.fast.q — same proxy-wrapped, read-only result.
roamAlphaAPI.data.q
await roamAlphaAPI.data.async.fast.q(
`[:find ?b :where [?e :block/uid ?b]]`)
// => proxy-wrapped results (read only)
roamAlphaAPI.data.search
search-str (string, required) — the search query (search-string is accepted as an alias)
search-blocks (boolean, optional, default true) — include block results
search-pages (boolean, optional, default true) — include page results
hide-code-blocks (boolean, optional, default: the user's hide-code-blocks setting) — exclude code blocks from results
limit (number, optional, default 300, max 1000) — maximum number of results
pull (string | array, optional, default [:block/string :node/title :block/uid]) — pull pattern for the returned fields
roamAlphaAPI.data.search({"search-str": "my query"})
// =>
[{":node/title": "My Query Notes",
":block/uid": "aBc123xYz"},
{":block/string": "a block mentioning my query",
":block/uid": "dEf456uVw"},
...]
roamAlphaAPI.data.semanticSearchEnabled
true when embeddings are enabled and a user is signed in. Synchronous.
roamAlphaAPI.data.async.semanticSearch, which throws when semantic search isn't available.
roamAlphaAPI.data.semanticSearchEnabled()
// => true
roamAlphaAPI.data.roamQuery
{{[[query]]: ...}} blocks — and return matching blocks/pages.
uid of an existing query block to use its stored settings
query string directly with optional display settings
roamAlphaAPI, the parameters are camelCase.
uid (string) — block uid of an existing query block; uses that block's stored display settings
query (string, required if no uid) — a query string, e.g. "{and: [[project]] [[active]]}"
groupByPage (boolean, optional, default true) — group results by page (query mode only)
nestUnderParent (boolean, optional, default false) — collapse child matches under their parent (query mode only)
sort (string, optional; query mode only)
groupByPage: "page-most-recent" (default) | "page-title" | "page-created-date" | "daily-note"
sortOrder (string, optional, default "desc") — "asc" or "desc" (query mode only)
offset (integer, optional, default 0) — number of results to skip
limit (integer | null, optional, default 20) — maximum results; pass null for all
pull (string, optional, default "[:block/string :node/title :block/uid]") — pull pattern for the results
{total: <number>, results: <array of pulled results>}
await window.roamAlphaAPI.data.roamQuery({query: "{and: [[project]] [[active]]}"})
// => {total: 42, results: [{":block/string": "...", ":block/uid": "aBc123xYz"}, ...]}
// run an existing query block with its stored settings
await window.roamAlphaAPI.data.roamQuery({uid: "abc123def"})
// => {total: 7, results: [...]}
roamAlphaAPI.data.addPullWatch
pattern (string, required) — the pull pattern to watch
entity-id (string, required) — the entity to watch, e.g. '[:block/uid "02-21-2021"]'
callback (function, required) — called with (before, after) pull results
null once the watch is registered
window.roamAlphaAPI.data.addPullWatch(
"[:block/children :block/string {:block/children ...}]",
'[:block/uid "02-21-2021"]',
(before, after) => { console.log("before", before, "after", after); })
// resolves to null; the callback later fires with the before/after pull results
roamAlphaAPI.data.removePullWatch
callback, removes every watch for that pattern + entity; with no arguments at all, removes all pull watches. Takes positional arguments.
pattern (string, optional) — the same value passed to roamAlphaAPI.data.addPullWatch
entity-id (string, optional) — the same value passed to roamAlphaAPI.data.addPullWatch
callback (function, optional) — the callback to remove
null (the two-argument form resolves to true)
window.roamAlphaAPI.data.removePullWatch(
"[:block/children :block/string {:block/children ...}]",
'[:block/uid "02-21-2021"]',
myCallbackFn)
// resolves to null
roamAlphaAPI.data.undo
cmd-z).
undefined
roamAlphaAPI.data.redo
cmd-shift-z).
undefined
roamAlphaAPI.data.block
roamAlphaAPI.data.block.create
roamAlphaAPI.createBlock (older top-level name; prefer this namespaced path)
location (object, required)
parent-uid (string, required) — uid of the parent block or page
order (number | "first" | "last", required) — position among the parent's children, 0-indexed
block (object, required)
string (string, required) — text content of the block
uid (string, optional) — autogenerated if omitted; pass one (see roamAlphaAPI.util.generateUID) only when you need to know it ahead of time
open (boolean, optional, default true) — collapse state
heading (integer, optional) — heading styling, 0 (none) to 3
text-align (string, optional) — "left" | "center" | "right" | "justify"
children-view-type (string, optional) — view type of the block's children: "bullet" | "numbered" | "document"
block-view-type (string, optional) — view type of the block itself: "outline" | "horizontal-outline" | "popout" | "tabs" | "comment" | "side" | "vertical"
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined; rejects if parent-uid doesn't exist or uid is already taken
await window.roamAlphaAPI.data.block.create(
{"location": {"parent-uid": "01-21-2021", "order": 0},
"block": {"string": "test"}})
// => undefined
roamAlphaAPI.data.block.update
roamAlphaAPI.updateBlock (older top-level name; prefer this namespaced path)
block (object, required)
uid (string, required) — block to update
string (string, optional) — new text content
open (boolean, optional) — collapse state
heading (integer, optional) — heading styling, 0 (none) to 3
text-align (string, optional) — "left" | "center" | "right" | "justify"
children-view-type (string, optional) — view type of the block's children: "bullet" | "numbered" | "document"
block-view-type (string, optional) — view type of the block itself: "outline" | "horizontal-outline" | "popout" | "tabs" | "comment" | "side" | "vertical"
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined
await window.roamAlphaAPI.data.block.update(
{"block": {"uid": "f8cXfDIRn", "string": "Love"}})
// => undefined
roamAlphaAPI.data.block.move
roamAlphaAPI.moveBlock (older top-level name; prefer this namespaced path)
block (object, required)
uid (string, required) — block to move
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
location (object, required)
parent-uid (string, required) — uid of the new parent block or page
order (number | "first" | "last", required) — position among the new parent's children
undefined; rejects if the block or parent-uid doesn't exist
await window.roamAlphaAPI.data.block.move(
{"location": {"parent-uid": "01-21-2021", "order": 0},
"block": {"uid": "f8cXfDIRn"}})
// => undefined
roamAlphaAPI.data.block.delete
roamAlphaAPI.deleteBlock (older top-level name; prefer this namespaced path)
block (object, required)
uid (string, required) — block to delete
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined
await window.roamAlphaAPI.data.block.delete(
{"block": {"uid": "f8cXfDIRn"}})
// => undefined
roamAlphaAPI.data.block.reorderBlocks
parent-uid — no other blocks, no duplicates — in the desired order.
location (object, required)
parent-uid (string, required) — uid of the new parent block or page
order (number | "first" | "last", required) — position among the new parent's children
blocks (array of strings, required) — every child uid of parent-uid, listed in the new order
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined
await roamAlphaAPI.data.block.reorderBlocks(
{location: {"parent-uid": "ihu5eUofL"},
blocks: ["QCE0cNNNL", "IATKcVmWE", "nC22orMO4"]})
// => undefined
roamAlphaAPI.data.block.fromMarkdown
# Hello followed by a two-item list parses to one top-level block with the list as its children. In outliner-shaped input (every non-blank line a - bullet or an indented continuation), headings stay flat labels — the same content written as - # Hello plus bullet items parses to flat siblings. (File import and paste always nest.)
location (object, required)
parent-uid (string, required) — uid of the new parent block or page
order (number | "first" | "last", required) — position among the new parent's children
markdown-string (string, required) — the markdown content to parse into blocks
{uids: [...]} — the uids of the top-level blocks created
await window.roamAlphaAPI.data.block.fromMarkdown({
location: {"parent-uid": "4VuwigG1O", "order": "first"},
"markdown-string": "# Hello\n\n- Item 1\n- Item 2\n - Nested"})
// => {uids: ["aBc123xYz"]}
// (one top-level block: the heading nests the list under it)
roamAlphaAPI.data.block.addComment
block-uid (string, required) — block to comment on
reply-string (string) — plain text for a single reply block (use this or reply-markdown, not both)
reply-markdown (string) — markdown parsed into multiple sibling reply blocks
reply-uid (string, optional) — uid for the created reply block; autogenerated if omitted
open-comment (boolean, optional, default false) — open the block's comments in the sidebar after adding the reply
{uids: [...], parentUid: "..."} — uids of the created reply block(s) and the uid of the comments block they live under
// single reply
await window.roamAlphaAPI.data.block.addComment(
{"block-uid": "abc123", "reply-string": "This is a comment"})
// => {uids: ["aBc123xYz"], parentUid: "dEf456uVw"}
// markdown reply (parsed into siblings)
await window.roamAlphaAPI.data.block.addComment(
{"block-uid": "abc123", "reply-markdown": "First block\n- Nested child"})
// => {uids: ["gHi789jKl"], parentUid: "dEf456uVw"}
roamAlphaAPI.data.page
roamAlphaAPI.data.page.create
January 21st, 2021) creates that daily note if it doesn't exist yet.
roamAlphaAPI.createPage (older top-level name; prefer this namespaced path)
page (object, required)
title (string, required)
uid (string, optional) — autogenerated if omitted; in normal operation you shouldn't pass one
children-view-type (string, optional) — "bullet" | "numbered" | "document"
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined; rejects if a page with the given title or uid already exists
await window.roamAlphaAPI.data.page.create({page: {title: "My New Page"}})
// => undefined
roamAlphaAPI.data.page.fromMarkdown
# Hello followed by a two-item list parses to one top-level block with the list as its children. In outliner-shaped input (every non-blank line a - bullet or an indented continuation), headings stay flat labels — the same content written as - # Hello plus bullet items parses to flat siblings. (File import and paste always nest.)
page (object, required)
title (string, required)
uid (string, optional) — autogenerated if omitted; in normal operation you shouldn't pass one
children-view-type (string, optional) — "bullet" | "numbered" | "document"
markdown-string (string, required) — the markdown content to parse into blocks
{uid: <page-uid>}; rejects if a page with the given title already exists
await window.roamAlphaAPI.data.page.fromMarkdown({
page: {title: "My New Page"},
"markdown-string": "# Heading\n\n- Item 1\n- Item 2"})
// => {uid: "mK9pQ2rTw"}
roamAlphaAPI.data.page.update
roamAlphaAPI.updatePage (older top-level name; prefer this namespaced path)
page (object, required)
uid (string, required)
title (string, optional) — new title
children-view-type (string, optional) — "bullet" | "numbered" | "document"
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined; rejects when renaming to a title that already exists in the graph
await window.roamAlphaAPI.data.page.update(
{page: {uid: "RZVuh3aZN", title: "New Title"}})
// => undefined
roamAlphaAPI.data.page.delete
roamAlphaAPI.deletePage (older top-level name; prefer this namespaced path)
page (object, required)
uid (string, required)
user-uid (string, optional) — attribute this write to the given user instead of the acting user; officially supported only from roamAlphaAPI.ai.addTool #experimental handlers
undefined
await window.roamAlphaAPI.data.page.delete({page: {uid: "RZVuh3aZN"}})
// => undefined
roamAlphaAPI.data.page.addShortcut
uid (string, required) — page uid
index (number, optional) — position in the shortcut list; defaults to the end (capped to the valid range)
undefined
await roamAlphaAPI.data.page.addShortcut("12-11-2025");
await roamAlphaAPI.data.page.addShortcut("12-11-2025", 4);
// each => undefined
roamAlphaAPI.data.page.removeShortcut
uid (string, required) — page uid
undefined
await roamAlphaAPI.data.page.removeShortcut("12-11-2025")
// => undefined
roamAlphaAPI.data.user
roamAlphaAPI.data.user.upsert
user-uid (string, required)
display-name (string, optional)
photo-url (string, optional) — url of the user's photo
undefined
await window.roamAlphaAPI.data.user.upsert(
{"user-uid": "BBG4fFwolaVlT5FZQdzAI7P40aB3",
"display-name": "Josh"})
// => undefined
roamAlphaAPI.data.ai
getPage, getBlock, getBacklinks, roamQuery, search, semanticSearch, suggestLinks, searchTemplates, getGraphGuidelines, getComments). Not a stable public surface — breaking changes land without notice; don't build on it. #experimental
roamAlphaAPI.ui
roamAlphaAPI.ui.getFocusedBlock
null if none. Synchronous.
roamAlphaAPI.ui.commandPalette callback, after the block has lost focus in the DOM.
{"block-uid": "YnatnbZzF",
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021"}
window.roamAlphaAPI.ui.getFocusedBlock()
// =>
{"block-uid": "YnatnbZzF",
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021"}
roamAlphaAPI.ui.setBlockFocusAndSelection
location (object, optional) — same shape as roamAlphaAPI.ui.getFocusedBlock's return value
block-uid (string, required)
window-id (string, required) — either:
roamAlphaAPI.ui.rightSidebar.getWindows
selection (object, optional)
start (integer, required) — 0-indexed
end (integer, optional)
start–end becomes a selection; otherwise the cursor is placed before the start-th character.
end is less than start, both are treated as the value of end.
undefined
window.roamAlphaAPI.ui.setBlockFocusAndSelection(
{location: window.roamAlphaAPI.ui.getFocusedBlock(),
selection: {start: 3, end: 7}})
// resolves to undefined
roamAlphaAPI.ui.mainWindow
roamAlphaAPI.ui.mainWindow.openBlock
block (object, required)
uid (string, required)
undefined
await window.roamAlphaAPI.ui.mainWindow.openBlock({block: {uid: "v9eHoHwqS"}})
// => undefined
roamAlphaAPI.ui.mainWindow.openPage
page (object, required) — one of:
title (string)
uid (string)
undefined
await window.roamAlphaAPI.ui.mainWindow.openPage({page: {title: "test-new"}})
await window.roamAlphaAPI.ui.mainWindow.openPage({page: {uid: "RZVuh3aZN"}})
// each => undefined
roamAlphaAPI.ui.mainWindow.openDailyNotes
undefined
roamAlphaAPI.ui.mainWindow.focusFirstBlock
undefined
roamAlphaAPI.ui.mainWindow.getOpenPageOrBlockUid
null when no page/block is open (e.g. the daily notes log)
await window.roamAlphaAPI.ui.mainWindow.getOpenPageOrBlockUid()
// => "Vfht187T1" (or null on the daily notes log)
roamAlphaAPI.ui.mainWindow.getOpenView
// page
{type: "outline",
uid: "Vfht187T1",
title: "My Page Title"}
// zoomed into a block
{type: "outline",
uid: "abc123xyz",
"block-string": "Some block content"}
// daily notes
{type: "log",
uids: ["07-17-2026", "07-16-2026"]}
// graph view
{type: "graph"}
// diagram
{type: "diagram",
uid: "diagram-uid"}
// PDF viewer
{type: "pdf",
uid: "pdf-block-uid",
url: "https://firebasestorage.googleapis.com/..."}
// all pages search
{type: "search"}
// custom component, see registerComponent
{type: "custom",
id: "component-id",
args: []}
roamAlphaAPI.ui.mainWindow.registerComponent
id (string, required) — identifier for the component
component (React component, required)
const MyView = () => React.createElement("h1", null, "Hello from my view");
window.roamAlphaAPI.ui.mainWindow.registerComponent("my-view", MyView)
// (return value is not meaningful)
roamAlphaAPI.ui.mainWindow.unregisterComponent
id (string, required)
window.roamAlphaAPI.ui.mainWindow.unregisterComponent("my-view")
// (return value is not meaningful)
roamAlphaAPI.ui.mainWindow.openComponent
roamAlphaAPI.ui.mainWindow.getOpenView as args.
id (string, required)
...args (optional) — arguments for the component
window.roamAlphaAPI.ui.mainWindow.openComponent("my-view", "arg1", 42)
// getOpenView() now reports
// {type: "custom", id: "my-view", args: ["arg1", 42]}
roamAlphaAPI.ui.mainWindow.closeComponent
id (string, required)
window.roamAlphaAPI.ui.mainWindow.closeComponent("my-view")
// (return value is not meaningful)
roamAlphaAPI.ui.leftSidebar
roamAlphaAPI.ui.leftSidebar.open
null
roamAlphaAPI.ui.leftSidebar.close
null
roamAlphaAPI.ui.rightSidebar
type plus target uid — there is no window-id argument. The window-id string from roamAlphaAPI.ui.rightSidebar.getWindows is only used with roamAlphaAPI.ui.setBlockFocusAndSelection.
block-uid with type "block" opens/matches an outline window for that page, and a mentions window becomes block- or page-mentions depending on the uid.
roamAlphaAPI.ui.rightSidebar.open
undefined
roamAlphaAPI.ui.rightSidebar.close
undefined
roamAlphaAPI.ui.rightSidebar.getWindows
type — "block" | "outline" | "mentions" | "graph" | "search-query"
window-id (string)
order (number), collapsed?, pinned?, pinned-to-top? (booleans)
type:
block-uid (plus block-string)
page-uid (plus title)
mentions-uid
page-uid plus title instead
search-query-str
window.roamAlphaAPI.ui.rightSidebar.getWindows()
// =>
[{type: "outline",
"window-id": "sidebar-outline-mK9pQ2rTw",
"page-uid": "mK9pQ2rTw",
title: "My Page",
order: 0,
"collapsed?": false,
"pinned?": false,
"pinned-to-top?": false},
{type: "block",
"window-id": "sidebar-block-aBc123xYz",
"block-uid": "aBc123xYz",
"block-string": "some block text",
order: 1,
"collapsed?": true,
"pinned?": false,
"pinned-to-top?": false}]
roamAlphaAPI.ui.rightSidebar.addWindow
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
order (number, optional) — position in the sidebar; if not specified, the new window is added at the top
undefined
// a block
window.roamAlphaAPI.ui.rightSidebar
.addWindow({window: {type: "block", "block-uid": "1fP8LY5ED"}})
// a page outline
window.roamAlphaAPI.ui.rightSidebar
.addWindow({window: {type: "outline", "block-uid": "cArVJL_vg"}})
// linked references of a block or page
window.roamAlphaAPI.ui.rightSidebar
.addWindow({window: {type: "mentions", "block-uid": "vutDCPD8G"}})
// a graph view of a page
window.roamAlphaAPI.ui.rightSidebar
.addWindow({window: {type: "graph", "block-uid": "cArVJL_vg"}})
// a window that searches for "API"
window.roamAlphaAPI.ui.rightSidebar
.addWindow({window: {type: "search-query", "search-query-str": "API"}})
// each resolves to undefined
roamAlphaAPI.ui.rightSidebar.removeWindow
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
undefined
window.roamAlphaAPI.ui.rightSidebar
.removeWindow({window: {type: "block", "block-uid": "1fP8LY5ED"}})
// resolves to undefined
roamAlphaAPI.ui.rightSidebar.expandWindow
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
undefined
window.roamAlphaAPI.ui.rightSidebar
.expandWindow({window: {type: "outline", "block-uid": "cArVJL_vg"}})
// resolves to undefined
roamAlphaAPI.ui.rightSidebar.collapseWindow
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
undefined
window.roamAlphaAPI.ui.rightSidebar
.collapseWindow({window: {type: "outline", "block-uid": "cArVJL_vg"}})
// resolves to undefined
roamAlphaAPI.ui.rightSidebar.pinWindow
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
pin-to-top? (boolean, optional) — true pins the window to the top: the pin turns red, new windows are added below it, and a previously top-pinned window is unpinned. When omitted, the pin-to-top state is left unchanged.
undefined
window.roamAlphaAPI.ui.rightSidebar
.pinWindow({window: {type: "block", "block-uid": "1fP8LY5ED"}})
// pin to the top of the sidebar
window.roamAlphaAPI.ui.rightSidebar
.pinWindow({window: {type: "block", "block-uid": "1fP8LY5ED"},
"pin-to-top?": true})
// each resolves to undefined
roamAlphaAPI.ui.rightSidebar.unpinWindow
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
undefined
window.roamAlphaAPI.ui.rightSidebar
.unpinWindow({window: {type: "block", "block-uid": "1fP8LY5ED"}})
// resolves to undefined
roamAlphaAPI.ui.rightSidebar.setWindowOrder
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required) — uid of the block or page the window shows; "search-query" windows take search-query-str instead
order (number, required) — new position, 0 to n
undefined
window.roamAlphaAPI.ui.rightSidebar
.setWindowOrder({window: {type: "block", "block-uid": "1fP8LY5ED", order: 0}})
// resolves to undefined
roamAlphaAPI.ui.filters
{"includes": [...page titles], "removes": [...page titles]}.
roamAlphaAPI.ui.filters.addGlobalFilter
title (string, required) — page title
type (string, required) — "includes" | "removes"
undefined
window.roamAlphaAPI.ui.filters
.addGlobalFilter({title: "TODO", type: "removes"})
// resolves to undefined
roamAlphaAPI.ui.filters.removeGlobalFilter
title (string, required) — page title
type (string, required) — "includes" | "removes"
undefined
window.roamAlphaAPI.ui.filters
.removeGlobalFilter({title: "TODO", type: "removes"})
// resolves to undefined
roamAlphaAPI.ui.filters.getGlobalFilters
{"includes": [...], "removes": [...]} — lists of page titles
window.roamAlphaAPI.ui.filters.getGlobalFilters()
// => {"includes": [], "removes": ["TODO"]}
roamAlphaAPI.ui.filters.getPageFilters
page (object, required) — one of:
title (string)
uid (string)
{"includes": [...], "removes": [...]} — lists of page titles
window.roamAlphaAPI.ui.filters.getPageFilters({page: {title: "test"}})
// => {"includes": ["March 11th, 2022"], "removes": []}
roamAlphaAPI.ui.filters.setPageFilters
{} as filters to clear them.
page (object, required) — one of:
title (string)
uid (string)
filters (object, required)
includes (array of page titles, optional)
removes (array of page titles, optional)
undefined
window.roamAlphaAPI.ui.filters.setPageFilters(
{page: {title: "test"},
filters: {includes: ["March 11th, 2022"]}})
// clear the filters
window.roamAlphaAPI.ui.filters.setPageFilters(
{page: {title: "test"}, filters: {}})
// each resolves to undefined
roamAlphaAPI.ui.filters.getPageLinkedRefsFilters
page (object, required) — one of:
title (string)
uid (string)
{"includes": [...], "removes": [...]} — lists of page titles
window.roamAlphaAPI.ui.filters.getPageLinkedRefsFilters({page: {title: "test"}})
// => {"includes": ["Author"], "removes": []}
roamAlphaAPI.ui.filters.setPageLinkedRefsFilters
{} as filters to clear them.
page (object, required) — one of:
title (string)
uid (string)
filters (object, required)
includes (array of page titles, optional)
removes (array of page titles, optional)
undefined
window.roamAlphaAPI.ui.filters.setPageLinkedRefsFilters(
{page: {title: "test"},
filters: {includes: ["Author"]}})
// resolves to undefined
roamAlphaAPI.ui.filters.getSidebarWindowFilters
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" ("search-query" windows don't support filters)
block-uid (string, required) — uid of the block or page the window shows
{"includes": [...], "removes": [...]} — lists of page titles
window.roamAlphaAPI.ui.filters.getSidebarWindowFilters(
{window: {"block-uid": "WYlc2nIO9", type: "outline"}})
// => {"includes": ["Author"], "removes": []}
roamAlphaAPI.ui.filters.setSidebarWindowFilters
{} as filters to clear them.
window (object, required)
type (string, required) — "block" | "outline" | "mentions" | "graph" ("search-query" windows don't support filters)
block-uid (string, required) — uid of the block or page the window shows
filters (object, required)
includes (array of page titles, optional)
removes (array of page titles, optional)
undefined
window.roamAlphaAPI.ui.filters.setSidebarWindowFilters(
{window: {"block-uid": "WYlc2nIO9", type: "outline"},
filters: {includes: ["Author"]}})
// resolves to undefined
roamAlphaAPI.ui.commandPalette
roamAlphaAPI.ui.commandPalette.addCommand
cmd-p).
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the Command Palette
callback (function, required) — called with no arguments when the user runs the command
disable-hotkey (boolean, optional) — don't allow a hotkey for this command
default-hotkey (string | array of strings, optional) — most commands should NOT set this
disable-hotkey is set), no hotkey is preassigned but the user can add one in Settings → Hotkeys.
["ctrl-c", "ctrl-m"] (like the native "go to next block").
cmd on macOS, ctrl elsewhere):
null
window.roamAlphaAPI.ui.commandPalette.addCommand(
{label: "hi",
callback: () => console.log("Hello World!")})
// with a default hotkey — in most cases you do NOT want this;
// the user can customize it in Settings → Hotkeys
window.roamAlphaAPI.ui.commandPalette.addCommand(
{label: "example1",
callback: () => console.log("Hello World!"),
"default-hotkey": "ctrl-cmd-l"})
// each resolves to null
roamAlphaAPI.ui.commandPalette.removeCommand
label from the Command Palette.
label (string, required) — the label passed to roamAlphaAPI.ui.commandPalette.addCommand
null
window.roamAlphaAPI.ui.commandPalette.removeCommand({label: "hi"})
// resolves to null
roamAlphaAPI.ui.slashCommand
roamAlphaAPI.ui.slashCommand.addCommand
/ slash menu. Calling again with the same label updates the existing command.
label (string, required) — text shown in the slash menu
display-conditional (function, optional) — called with the context object (without indexes); return true to show the command
callback (function, required)
{"block-uid": "YnatnbZzF",
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021",
indexes: [1, 10]}
null to handle insertion yourself (the typed search string is not removed).
null
window.roamAlphaAPI.ui.slashCommand.addCommand({
label: "Quick Test",
callback: (context) => "It works! 🎉"
});
// => null
roamAlphaAPI.ui.slashCommand.removeCommand
label from the slash menu.
label (string, required) — the label passed to roamAlphaAPI.ui.slashCommand.addCommand
null
window.roamAlphaAPI.ui.slashCommand.removeCommand({label: "Quick Test"})
// => null
roamAlphaAPI.ui.blockContextMenu
roamAlphaAPI.ui.blockContextMenu.addCommand
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the menu
display-conditional (function, optional) — called with the block context every time the menu opens; return true to include the command for that block
callback (function, required)
{"block-string": "Todos",
"block-uid": "YnatnbZzF",
heading: null,
"page-uid": "04-15-2021",
"read-only?": false,
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021"}
null
roamAlphaAPI.ui.blockContextMenu.addCommand(
{label: "Debug: Console Log",
"display-conditional": (e) => e["block-string"].includes("Test Block"),
callback: (e) => console.log(e)})
// resolves to null
roamAlphaAPI.ui.blockContextMenu.removeCommand
label.
label (string, required)
null
roamAlphaAPI.ui.blockContextMenu.removeCommand({label: "Debug: Console Log"})
// resolves to null
roamAlphaAPI.ui.pageContextMenu
roamAlphaAPI.ui.pageContextMenu.addCommand
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the menu
display-conditional (function, optional) — called with the context object; return true to show the command
callback (function, required)
{"page-uid": "YnatnbZzF",
"page-title": "title",
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021"}
null
roamAlphaAPI.ui.pageContextMenu.addCommand(
{label: "Debug: Console Log", callback: (e) => console.log(e)})
// => null
roamAlphaAPI.ui.pageContextMenu.removeCommand
label.
label (string, required)
null
roamAlphaAPI.ui.pageContextMenu.removeCommand({label: "Debug: Console Log"})
// => null
roamAlphaAPI.ui.pageRefContextMenu
roamAlphaAPI.ui.pageRefContextMenu.addCommand
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the menu
display-conditional (function, optional) — called with the context object; return true to show the command
callback (function, required)
{"ref-uid": "YnatnbZzF",
"block-uid": "xyz", // containing block
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021",
indexes: [0, 9], // outer indexes in the block string
type: "attribute"}
type values:
[[test]]
test::
#test
#[[Test]]
[t]([[Test]])
null
roamAlphaAPI.ui.pageRefContextMenu.addCommand(
{label: "Debug: Console Log", callback: (e) => console.log(e)})
// => null
roamAlphaAPI.ui.pageRefContextMenu.removeCommand
label.
label (string, required) — the label passed to roamAlphaAPI.ui.pageRefContextMenu.addCommand
null
roamAlphaAPI.ui.pageRefContextMenu.removeCommand({label: "Debug: Console Log"})
// => null
roamAlphaAPI.ui.blockRefContextMenu
roamAlphaAPI.ui.blockRefContextMenu.addCommand
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the menu
display-conditional (function, optional) — called with the context object; return true to show the command
callback (function, required)
{"ref-uid": "YnatnbZzF",
"block-uid": "abc123xyz", // containing block
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021",
indexes: [0, 9]} // outer indexes in the block string
null
roamAlphaAPI.ui.blockRefContextMenu.addCommand(
{label: "Debug: Console Log", callback: (e) => console.log(e)})
// => null
roamAlphaAPI.ui.blockRefContextMenu.removeCommand
label.
label (string, required)
null
roamAlphaAPI.ui.blockRefContextMenu.removeCommand({label: "Debug: Console Log"})
// => null
roamAlphaAPI.ui.pageLinkContextMenu
roamAlphaAPI.ui.pageLinkContextMenu.addCommand
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the menu
display-conditional (function, optional) — called with the context object; return true to show the command
callback (function, required)
{"page-uid": "YnatnbZzF",
"page-title": "title"}
null
roamAlphaAPI.ui.pageLinkContextMenu.addCommand(
{label: "Debug: Console Log", callback: (e) => console.log(e)})
// => null
roamAlphaAPI.ui.pageLinkContextMenu.removeCommand
label.
label (string, required)
null
roamAlphaAPI.ui.pageLinkContextMenu.removeCommand({label: "Debug: Console Log"})
// => null
roamAlphaAPI.ui.msContextMenu
roamAlphaAPI.ui.msContextMenu.addCommand
label updates the existing command instead of adding a second one.
label (string, required) — text shown in the menu
display-conditional (function, optional) — return true to show the command
callback (function, required) — called when the user selects the command
null
window.roamAlphaAPI.ui.msContextMenu.addCommand(
{label: "test", callback: () => { console.log("hey") }})
// => null
roamAlphaAPI.ui.msContextMenu.removeCommand
label.
label (string, required)
null
window.roamAlphaAPI.ui.msContextMenu.removeCommand({label: "test"})
// => null
roamAlphaAPI.ui.multiselect.getSelected
{"block-uid", "window-id"} objects; empty array if nothing is selected
window.roamAlphaAPI.ui.multiselect.getSelected()
// => [{"block-uid": "Vfht187T1", "window-id": "main-window"},
// {"block-uid": "abc123xyz", "window-id": "main-window"}]
roamAlphaAPI.ui.individualMultiselect.getSelectedUids
cmd-m). Synchronous.
window.roamAlphaAPI.ui.individualMultiselect.getSelectedUids()
// => ["Vfht187T1", "abc123xyz"]
roamAlphaAPI.ui.graphView
roamAlphaAPI.ui.graphView.addCallback
roamAlphaAPI.ui.graphView.wholeGraph.
label (string, required) — used to upsert or remove the callback
callback (function, required)
context when the user selects the command in the Command Palette
cytoscape — the Cytoscape graph object
elements — array of the nodes and edges in the graph
type — "page" | "all-pages" (only "page" occurs now)
{cytoscape: Core {_private: {…}},
elements: [
{id: "eTCpkG-HI", name: "B", weight: 7},
{id: "05-04-2021", name: "May 4th, 2021", weight: 10},
{id: "eTCpkG-HI-FrW4nHLat", source: "eTCpkG-HI", target: "FrW4nHLat"}
],
type: "page"}
type (string, deprecated) — only "page" views fire anymore, so this filter is pointless; omit it
null, but the return value is internal — treat it as void
roamAlphaAPI.ui.graphView.addCallback({
label: "my-extension: graph loaded",
type: "page",
callback: ({cytoscape, elements, type}) => console.log(type, elements)})
// (return value is not meaningful)
roamAlphaAPI.ui.graphView.removeCallback
label.
label (string, required)
null (synchronous)
roamAlphaAPI.ui.graphView.removeCallback({label: "my-extension: graph loaded"})
// => null
roamAlphaAPI.ui.graphView.wholeGraph
roamAlphaAPI.ui.graphView.wholeGraph.setMode
mode (string, required) — "Whole Graph" | "Explore"
roamAlphaAPI.ui.graphView.wholeGraph.setMode("Explore")
// (return value is not meaningful)
roamAlphaAPI.ui.graphView.wholeGraph.setExplorePages
pages (array of page titles, required) — throws if any title doesn't exist in the graph
roamAlphaAPI.ui.graphView.wholeGraph.setExplorePages(["My Project"])
// (return value is not meaningful)
roamAlphaAPI.ui.graphView.wholeGraph.getExplorePages
roamAlphaAPI.ui.graphView.wholeGraph.getExplorePages()
// => ["My Project"]
roamAlphaAPI.ui.graphView.wholeGraph.addCallback
label (string, required) — used to upsert or remove the callback
callback (function, required) — called with {"sigma-renderer": <Sigma renderer>} when the overview mounts
null
roamAlphaAPI.ui.graphView.wholeGraph.addCallback({
label: "test",
callback: ({"sigma-renderer": renderer}) => console.log(renderer)})
// => null
roamAlphaAPI.ui.graphView.wholeGraph.removeCallback
label.
label (string, required)
null
roamAlphaAPI.ui.graphView.wholeGraph.removeCallback({label: "test"})
// => null
roamAlphaAPI.ui.components
roamAlphaAPI.ui.components.unmountNode; for declarative React/JSX components, see roamAlphaAPI.ui.react.
roamAlphaAPI.ui.components.renderBlock
uid (string, required) — block to display
el (DOM node, required) — where to mount the component
open? (boolean, optional) — true forces the block open (children shown), false forces it closed; omitted = whatever the block's open state is in the graph
zoom-path? (boolean, optional) — show the zoom path above the block (similar to how linked references look)
zoom-start-after-uid (string, optional; only valid with zoom-path?)
... for everything before this uid
null
const newNode = document.createElement("div");
const wrap = document.getElementById("right-sidebar");
wrap.insertBefore(newNode, wrap.firstChild);
window.roamAlphaAPI.ui.components.renderBlock(
{uid: "6-P4ZEbIY",
el: newNode,
"open?": false,
"zoom-path?": true,
"zoom-start-after-uid": "ImSvJvm1_"})
// resolves to null once mounted
roamAlphaAPI.ui.components.renderPage
roamAlphaAPI.ui.components.renderBlock unless you need zoom-path? (block-only) or hide-mentions? (page-only).
uid (string, required) — page to display
el (DOM node, required)
hide-mentions? (boolean, optional) — hide the linked references at the bottom of the page
null
const newNode = document.createElement("div");
document.body.appendChild(newNode);
window.roamAlphaAPI.ui.components.renderPage(
{uid: "mK9pQ2rTw",
el: newNode,
"hide-mentions?": true})
// resolves to null once mounted
roamAlphaAPI.ui.components.renderSearch
cmd-u search) into a DOM node. Also available as the {{[[search]]: query}} component. CSS classes: rm-search-query, plus the existing rm-query.
search-query-str (string, required) — the search query
el (DOM node, required)
closed? (boolean, optional, default false) — collapse the view
group-by-page? (boolean, optional, default false) — group results by page
hide-paths? (boolean, optional, default false) — hide block paths in results
config-changed-callback (function, optional) — called with the new config when the user changes the view's configuration
null
const newNode = document.createElement("div");
const wrap = document.getElementById("right-sidebar");
wrap.insertBefore(newNode, wrap.firstChild);
window.roamAlphaAPI.ui.components.renderSearch(
{"search-query-str": "Bret Victor",
el: newNode,
"group-by-page?": false,
"config-changed-callback": (config) => console.log("new config", config)})
// resolves to null once mounted
roamAlphaAPI.ui.components.renderString
[[Page Title]] links for pages that don't exist — those links won't work.
string (string, required) — the string to render
el (DOM node, required)
null
window.roamAlphaAPI.ui.components.renderString(
{el: newNode,
string: "Hello via [[Roam Alpha API]]'s `renderString` — supports ((abc123xyz)) refs too"})
// resolves to null once mounted
roamAlphaAPI.ui.components.unmountNode
el (DOM node, required) — the node the component was mounted in
null
window.roamAlphaAPI.ui.components.unmountNode({el: newNode})
// resolves to null
roamAlphaAPI.ui.react
roamAlphaAPI.ui.components. Note the props are camelCase, unlike its kebab-case keys.
roamAlphaAPI.ui.react.Block
uid (string, required) — block to display
open (boolean, optional) — force open/closed; omitted = the block's open state in the graph
zoomPath (boolean, optional) — show the zoom path
zoomStartAfterUid (string, optional; only valid with zoomPath) — compact the path to ... before this uid
const { Block } = window.roamAlphaAPI.ui.react;
<Block uid="6-P4ZEbIY" />
<Block uid="6-P4ZEbIY" open={false} />
<Block uid="6-P4ZEbIY" zoomPath={true} zoomStartAfterUid="ImSvJvm1_" />
roamAlphaAPI.ui.react.Page
uid (string) / title (string) — one of the two is required
hideMentions (boolean, optional) — hide the linked references section at the bottom
const { Page } = window.roamAlphaAPI.ui.react;
<Page uid="page-uid-123" />
<Page title="My Page" hideMentions={true} />
roamAlphaAPI.ui.react.Search
searchQueryStr (string, required) — the search query
closed (boolean, optional) — collapse the view
groupByPage (boolean, optional) — group results by their page
hidePaths (boolean, optional) — hide block paths in results
onConfigChange (function, optional) — called with the new config object when the user changes grouping etc.
const { Search } = window.roamAlphaAPI.ui.react;
<Search searchQueryStr="Bret Victor" groupByPage={true}
onConfigChange={(config) => console.log(config)} />
roamAlphaAPI.ui.react.BlockString
[[page links]], ((block refs)), formatting. The rendered content is not editable.
string (string, required) — the Roam-markdown string to render
const { BlockString } = window.roamAlphaAPI.ui.react;
<BlockString string="Hello [[World]]" />
<BlockString string="This is **bold** and __italic__" />
roamAlphaAPI.ui.callout
roamAlphaAPI.ui.callout.addType
[!type] syntax.
.rm-callout--{type} for the color and .rm-callout--{type} .rm-callout__icon for the icon. A built-in default icon shows until your CSS loads.
type (string, required) — the string used in the [!type] callout syntax
null
window.roamAlphaAPI.ui.callout.addType({type: "recipe"})
// => null
roam/css or an extension stylesheet:
.rm-callout--recipe {
--callout-color: #f778ba;
}
.rm-callout--recipe .rm-callout__icon::before {
content: "🍪";
font-family: initial;
}
roamAlphaAPI.ui.callout.removeType
type (string, required) — the type string to remove
null
window.roamAlphaAPI.ui.callout.removeType({type: "recipe"})
// => null
roamAlphaAPI.util
roamAlphaAPI.util.generateUID
window.roamAlphaAPI.util.generateUID()
// => "aB3xK9mP2"
roamAlphaAPI.util.pageTitleToDate
title (string, required) — a daily note title like "June 16th, 2022"
null for anything that isn't a daily note title
roamAlphaAPI.util.pageTitleToDate("June 16th, 2022")
// => Date Thu Jun 16 2022 00:00:00
roamAlphaAPI.util.pageTitleToDate("not a daily note title")
// => null
roamAlphaAPI.util.dateToPageTitle
date (Date, required) — a JavaScript Date
roamAlphaAPI.util.dateToPageTitle(new Date(2022, 5, 16))
// => "June 16th, 2022"
roamAlphaAPI.util.dateToPageUid
roamAlphaAPI.util.generateUID when programmatically creating a daily note page and you need its uid ahead of time.
date (Date, required) — a JavaScript Date
roamAlphaAPI.util.dateToPageUid(new Date(2022, 5, 16))
// => "06-16-2022"
roamAlphaAPI.file
roamAlphaAPI.file.upload
roamAlphaAPI.util.uploadFile — prefer this version; the old one won't be removed.
file (File, required) — a File object
toast (object, optional)
hide (boolean, optional, default false) — hide the upload toast
 for images, {{[[pdf]]: url}} / {{[[audio]]: url}} / {{[[video]]: url}} for those media types — or the bare download url (string) for other file types
await roamAlphaAPI.file.upload({file: myImageFile, toast: {hide: true}})
// => ""
await roamAlphaAPI.file.upload({file: new File([""], "notes.txt")})
// => "https://firebasestorage.googleapis.com/..." (bare url — not a recognized media type)
roamAlphaAPI.file.get
fetch the url yourself, but get handles decryption on encrypted graphs and restores the original file name and type metadata.
url (string, required) — a firebase storage url, obtained from roamAlphaAPI.file.upload or from a block
format (string, optional) — pass "base64" to resolve with {base64, filename, mimetype} instead of a File object
format: "base64", to {base64, filename, mimetype}
await roamAlphaAPI.file.get({url: "https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/..."})
// => File {name: "GVfB6XBcMR.pdf", type: "application/pdf", size: 183424, ...}
roamAlphaAPI.file.delete
url (string, required) — a firebase storage url, obtained from roamAlphaAPI.file.upload or from a block
undefined
await roamAlphaAPI.file.delete({url: "https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/..."})
// => undefined
roamAlphaAPI.user
roamAlphaAPI.user.uid
roamAlphaAPI.data.pull to get the user's display page and other metadata.
null when not signed in
roamAlphaAPI.user.uid()
// => "BBG4fFwolaVlT5FZQdzAI7P40aB3" (or null when signed out)
// pull all info about the current user
roamAlphaAPI.data.pull("[*]", [":user/uid", window.roamAlphaAPI.user.uid()]);
// => {":user/uid": "BBG4fFwolaVlT5FZQdzAI7P40aB3", ":user/display-name": "Josh", ...}
roamAlphaAPI.user.isAdmin
roamAlphaAPI.graph
roamAlphaAPI.graph.name (string) — the name of the current graph
roamAlphaAPI.graph.type (string) — "hosted" | "offline"
roamAlphaAPI.graph.isEncrypted (boolean) — whether the graph is encrypted
roamAlphaAPI.platform
roamAlphaAPI.platform.isDesktop (boolean) — true in the Roam Desktop App
roamAlphaAPI.platform.isMobileApp (boolean) — true in the Roam Mobile App
roamAlphaAPI.platform.isMobile (boolean) — true on small screens; purely a screen-size check (media query max-width: 450px)
roamAlphaAPI.platform.isIOS (boolean) — true on iPhone, iPad, or iPod
roamAlphaAPI.platform.isPC (boolean) — true on a PC; useful for offering different shortcuts on PC vs Mac
roamAlphaAPI.platform.isTouchDevice (boolean) — true on touch devices
roamAlphaAPI.depot
roamAlphaAPI.depot.getInstalledExtensions
{ext-id: ext-map}; version is "DEV" for developer-loaded extensions
roamAlphaAPI.depot.getInstalledExtensions()
// =>
{"ccc+ccc-roam-pdf-2":
{id: "ccc+ccc-roam-pdf-2",
name: "Roam PDF Highlighter 2",
enabled: false,
adminEnabled: true,
version: "1"},
...}
roamAlphaAPI.depot.reloadDeveloperExtensions
ctrl-d ctrl-r).
await roamAlphaAPI.depot.reloadDeveloperExtensions()
// => {reloaded: [{id: "dev-extension-id", name: "My Dev Extension"}]}
roamAlphaAPI.ai
roamAlphaAPI.ai.addTool #experimental
name updates the existing tool instead of adding a second one, so re-running a script is safe.
roamAlphaAPI.data.ai.getGraphGuidelines (as extensionTools) and invoked via roamAlphaAPI.data.ai.callExtensionTool.
name, graph-wide, and are never removed automatically — the registering script owns the lifecycle. Roam Depot extensions should use extensionAPI.ai.addTool #experimental instead: same arguments, but tools are namespaced by extension and removed automatically on unload.
inputSchema (if provided) before handler runs.
name (string, required) — the id agents call the tool by; up to 64 characters from A-Za-z0-9_-
description (string, required) — tells the agent what the tool does and when to use it; up to 2000 characters
handler (function, required)
context object (below); returns a JSON-serializable value or a Promise resolving to one
context.tokenUserUid (string) — uid of the AI user the call came from; absent when the tool is invoked directly from JS
user-uid argument (e.g. block: {..., "user-uid": context.tokenUserUid}) to attribute writes to the AI — including writes made after the handler's first await.
context.asTokenUser(fn) — runs fn with the graph writes it issues attributed to the calling AI, with the AI's token scopes in effect
scope (string, optional, default "edit") — "read" | "append" | "edit"
inputSchema (object, optional)
handler's args
$schema, if present, must be the draft-07 URI — schemas are always validated as draft-07.
type, if present, must be "object" — a tool's args are always a plain object.
handler runs; when absent, args reach the handler unvalidated.
null
window.roamAlphaAPI.ai.addTool({
name: "word-count",
description: "Counts words in a block's text.",
scope: "read",
inputSchema: {
type: "object",
properties: {uid: {type: "string", description: "The block's uid"}},
required: ["uid"]
},
handler: ({uid}) => {
const s = window.roamAlphaAPI.pull("[:block/string]", [":block/uid", uid])[":block/string"] || "";
return {words: s.trim() ? s.trim().split(/\s+/).length : 0};
}
}) // => null
roamAlphaAPI.ai.removeTool #experimental
roamAlphaAPI.ai.addTool #experimental. Removing a name that isn't registered does nothing.
name (string, required) — the registered tool's name
null
window.roamAlphaAPI.ai.removeTool({name: "word-count"}) // => null
roamAlphaAPI.constants
roamAlphaAPI.constants.corsAnywhereProxyUrl
url directly, fetch ${roamAlphaAPI.constants.corsAnywhereProxyUrl}/${url}.
https://roamresearch.com.
let urlToFetch = "https://google.com"
await fetch(`${roamAlphaAPI.constants.corsAnywhereProxyUrl}/${urlToFetch}`)
.then(a => a.text())
// => "<!doctype html><html ...>" (the fetched page's body as text)
event.dataTransfer.getData(type) in your own drop handlers.
myPanel.addEventListener("drop", (e) => {
const uids = e.dataTransfer.getData("roam/block-uid-list-only-parents").split("\n")
console.log("dropped blocks:", uids)
})
// dragging a page from the left sidebar carries its page uid instead