Roam Research Docs · Developer documentation
window object as window.roamAlphaAPI and is available from roam/js code blocks, Roam Depot extensions, and the browser console.
? — quote them in JS: {"parent-uid": "abc", "zoom-path?": true}. Exceptions: data.roamQuery uses camelCase keys, and a few functions take positional arguments (data.addPullWatch, data.page.addShortcut, ui.mainWindow.registerComponent, everything in util).
null once Roam has applied the operation — after the triggering event and all of its descendant events are handled. Chain dependent writes with await; no setTimeout hacks needed.
.catch(), or try/catch with await.
Returns:: says otherwise (data.roamQuery, ui.mainWindow.getOpenView, and ui.mainWindow.getOpenPageOrBlockUid return promises). Prefer the promise-returning data.async.* variants in new code — the synchronous reads will eventually be deprecated.
q, pull, pull_many and their variants time out after 20 seconds, throwing Query and/or pull expression took too long to run. — pull and pull_many accept an options argument to override the timeout.
util.generateUID.
MM-DD-YYYY format (e.g. 07-16-2026 for July 16th, 2026) — see util.dateToPageUid.
roamAlphaAPI.apiVersion is a string property (e.g. "1.1.3") — use it for feature detection.
window argument
ui.rightSidebar window functions and ui.filters.getSidebarWindowFilters/setSidebarWindowFilters:
type (string, required) — one of "block" | "outline" | "mentions" | "graph" | "search-query"
block-uid (string, required for every type except "search-query") — uid of the block or page the window shows
search-query-str (string, required when type is "search-query", in place of block-uid) — the search query
roamAlphaAPI.data — queries and reads, plus the write API for blocks, pages, and users
roamAlphaAPI.data.q
roamAlphaAPI.q (older top-level name; prefer this namespaced path)
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
data.pull, but for many entities at once — faster than pulling in a loop. Synchronous.
pattern (string, required) — same as data.pull's pattern
eids (array, required) — array of eids, each in any of the forms 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
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
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, semanticSearch, fast.q.
async.search uses the indexed search worker when available, transparently falling back to the standard search — same parameters and return shape as data.search, wrapped in a promise.
async.semanticSearch is async-only and documented below.
await roamAlphaAPI.data.async.q(
`[:find ?s
:where [?e :block/string ?s]]`)
// => [["some block text"], ...]
await roamAlphaAPI.data.async.pull("[*]", [":block/uid", "xyz"])
// => {":block/uid": "xyz", ":block/string": "the block's text", ...}
roamAlphaAPI.data.search
search-str (string, required) — the search query
search-blocks (boolean, optional, default true) — include block results
search-pages (boolean, optional, default true) — include page results
hide-code-blocks (boolean, optional, default false) — 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.
data.async.semanticSearch, which throws when semantic search isn't available.
roamAlphaAPI.data.semanticSearchEnabled()
// => true
roamAlphaAPI.data.async.semanticSearch
data.semanticSearchEnabled() first. While embeddings are still indexing, it returns partial results rather than throwing.
search-str (string, required) — the search query
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.roamQuery
{{[[query]]: ...}} blocks — and return matching blocks/pages.
uid of an existing query block to use its stored settings, or pass a 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 false) — 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) — with groupByPage: "page-most-recent" (default) | "page-title" | "page-created-date" | "daily-note"; without: "created-date" (default) | "edited-date" | "daily-note-date"
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 addPullWatch
entity-id (string, optional) — the same value passed to addPullWatch
callback (function, optional) — the callback to remove
null
window.roamAlphaAPI.data.removePullWatch(
"[:block/children :block/string {:block/children ...}]",
'[:block/uid "02-21-2021"]',
myCallbackFn)
// resolves to null
roamAlphaAPI.data.undo
cmd-z).
null
await window.roamAlphaAPI.data.undo()
// => null
roamAlphaAPI.data.redo
cmd-shift-z).
null
await window.roamAlphaAPI.data.redo()
// => null
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.
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 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"
null; 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"}})
// => null
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, heading, text-align, children-view-type, block-view-type — all optional, same values as in data.block.create
null
await window.roamAlphaAPI.data.block.update(
{"block": {"uid": "f8cXfDIRn", "string": "Love"}})
// => null
roamAlphaAPI.data.block.move
roamAlphaAPI.moveBlock (older top-level name; prefer this namespaced path)
block (object, required)
uid (string, required) — block to move
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
null; 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"}})
// => null
roamAlphaAPI.data.block.delete
roamAlphaAPI.deleteBlock (older top-level name; prefer this namespaced path)
block (object, required)
uid (string, required) — block to delete
null
await window.roamAlphaAPI.data.block.delete(
{"block": {"uid": "f8cXfDIRn"}})
// => null
roamAlphaAPI.data.block.reorderBlocks
parent-uid — no other blocks, no duplicates — in the desired order.
location (object, required)
parent-uid (string, required)
blocks (array of strings, required) — every child uid of parent-uid, listed in the new order
null
await roamAlphaAPI.data.block.reorderBlocks(
{location: {"parent-uid": "ihu5eUofL"},
blocks: ["QCE0cNNNL", "IATKcVmWE", "nC22orMO4"]})
// => null
roamAlphaAPI.data.block.fromMarkdown
location (object, required)
parent-uid (string, required)
order (number | "first" | "last", required)
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", "dEf456uVw", "gHi789jKl"]}
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
null
// single reply
await window.roamAlphaAPI.data.block.addComment(
{"block-uid": "abc123", "reply-string": "This is a comment"})
// => null
// markdown reply (parsed into siblings)
await window.roamAlphaAPI.data.block.addComment(
{"block-uid": "abc123", "reply-markdown": "First block\n- Nested child"})
// => null
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"
null; rejects if a page with the given title or uid already exists
await window.roamAlphaAPI.data.page.create({page: {title: "My New Page"}})
// => null
roamAlphaAPI.data.page.fromMarkdown
page (object, required) — same keys as data.page.create
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"
null; rejects when renaming to a title that already exists in the graph
await window.roamAlphaAPI.data.page.update(
{page: {uid: "RZVuh3aZN", title: "New Title"}})
// => null
roamAlphaAPI.data.page.delete
roamAlphaAPI.deletePage (older top-level name; prefer this namespaced path)
page (object, required)
uid (string, required)
null
await window.roamAlphaAPI.data.page.delete({page: {uid: "RZVuh3aZN"}})
// => null
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)
null
await roamAlphaAPI.data.page.addShortcut("12-11-2025");
await roamAlphaAPI.data.page.addShortcut("12-11-2025", 4);
// each => null
roamAlphaAPI.data.page.removeShortcut
uid (string, required) — page uid
null
await roamAlphaAPI.data.page.removeShortcut("12-11-2025")
// => null
roamAlphaAPI.data.user
roamAlphaAPI.data.user.upsert
user-uid (string, required)
display-name (string, optional)
null
await window.roamAlphaAPI.data.user.upsert(
{"user-uid": "BBG4fFwolaVlT5FZQdzAI7P40aB3",
"display-name": "Josh"})
// => null
roamAlphaAPI.ui — everything that drives the interface: focus, windows, sidebars, filters, menus, and custom components
roamAlphaAPI.ui.getFocusedBlock
null if none. Synchronous.
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; defaults to the currently focused block) — same shape as ui.getFocusedBlock's return value
block-uid (string, required)
window-id (string, required) — a window id from ui.rightSidebar.getWindows, or the string "main-window"
selection (object, optional; without it the cursor is placed at the end of the string)
start (integer, required) — 0-indexed
end (integer, optional) — with end, start–end becomes a selection; without it, the cursor is placed before the start-th character. If end is less than start, both are treated as the value of end.
null
window.roamAlphaAPI.ui.setBlockFocusAndSelection(
{location: window.roamAlphaAPI.ui.getFocusedBlock(),
selection: {start: 3, end: 7}})
// resolves to null
roamAlphaAPI.ui.mainWindow
roamAlphaAPI.ui.mainWindow.openBlock
{block: {uid: "10-16-2021"}} opens that daily note.
block (object, required)
uid (string, required)
null
await window.roamAlphaAPI.ui.mainWindow.openBlock({block: {uid: "v9eHoHwqS"}})
// => null
roamAlphaAPI.ui.mainWindow.openPage
page (object, required) — one of:
title (string)
uid (string)
null
await window.roamAlphaAPI.ui.mainWindow.openPage({page: {title: "test-new"}})
await window.roamAlphaAPI.ui.mainWindow.openPage({page: {uid: "RZVuh3aZN"}})
// each => null
roamAlphaAPI.ui.mainWindow.openDailyNotes
null
await window.roamAlphaAPI.ui.mainWindow.openDailyNotes()
// => null
roamAlphaAPI.ui.mainWindow.focusFirstBlock
null
await window.roamAlphaAPI.ui.mainWindow.focusFirstBlock()
// => null
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"}
// graph view
{type: "graph"}
// diagram
{type: "diagram",
uid: "diagram-uid"}
// PDF viewer
{type: "pdf",
uid: "pdf-block-uid"}
// 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)
null
roamAlphaAPI.ui.mainWindow.unregisterComponent
id (string, required)
null
roamAlphaAPI.ui.mainWindow.openComponent
getOpenView as args.
id (string, required)
...args (optional) — arguments for the component
null
roamAlphaAPI.ui.mainWindow.closeComponent
id (string, required)
null
roamAlphaAPI.ui.leftSidebar
roamAlphaAPI.ui.leftSidebar.open
null
roamAlphaAPI.ui.leftSidebar.close
null
roamAlphaAPI.ui.rightSidebar
roamAlphaAPI.ui.rightSidebar.open
null
roamAlphaAPI.ui.rightSidebar.close
null
roamAlphaAPI.ui.rightSidebar.getWindows
type — "block" | "outline" | "mentions" | "graph" | "search-query"
window-id (string) — usable with e.g. ui.setBlockFocusAndSelection
order (number), collapsed?, pinned?, pinned-to-top? (booleans)
type: block-uid (plus block-string), page-uid (plus title), mentions-uid, or search-query-str
window.roamAlphaAPI.ui.rightSidebar.getWindows()
// =>
[{type: "outline",
"window-id": "...",
"page-uid": "mK9pQ2rTw",
title: "My Page",
order: 0,
"collapsed?": false,
"pinned?": false,
"pinned-to-top?": false},
{type: "block",
"window-id": "...",
"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) — see sidebar window argument, plus:
order (number, optional) — position in the sidebar; if not specified, the new window is added at the top
class (string | array of strings, optional) — CSS class(es) added to the window's element
null
// 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 window that searches for "API"
window.roamAlphaAPI.ui.rightSidebar
.addWindow({window: {type: "search-query", "search-query-str": "API"}})
// each resolves to null
roamAlphaAPI.ui.rightSidebar.removeWindow
window (object, required) — see sidebar window argument
null
window.roamAlphaAPI.ui.rightSidebar
.removeWindow({window: {type: "block", "block-uid": "1fP8LY5ED"}})
// resolves to null
roamAlphaAPI.ui.rightSidebar.expandWindow
window (object, required) — see sidebar window argument
null
roamAlphaAPI.ui.rightSidebar.collapseWindow
window (object, required) — see sidebar window argument
null
roamAlphaAPI.ui.rightSidebar.pinWindow
window (object, required) — see sidebar window argument
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.
null
roamAlphaAPI.ui.rightSidebar.unpinWindow
window (object, required) — see sidebar window argument
null
roamAlphaAPI.ui.rightSidebar.setWindowOrder
window (object, required) — see sidebar window argument, plus:
order (number, required) — new position, 0 to n
null
roamAlphaAPI.ui.filters
{"includes": [...page titles], "removes": [...page titles]}.
roamAlphaAPI.ui.filters.addGlobalFilter
title (string, required) — page title
type (string, required) — "includes" | "removes"
null
roamAlphaAPI.ui.filters.removeGlobalFilter
title (string, required) — page title
type (string, required) — "includes" | "removes"
null
roamAlphaAPI.ui.filters.getGlobalFilters
{"includes": [...], "removes": [...]} — lists of page titles
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 | uid
filters (object, required)
includes (array of page titles, optional)
removes (array of page titles, optional)
null
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 null
roamAlphaAPI.ui.filters.getPageLinkedRefsFilters
page (object, required) — one of title | uid
{"includes": [...], "removes": [...]} — lists of page titles
roamAlphaAPI.ui.filters.setPageLinkedRefsFilters
{} as filters to clear them.
page (object, required) — one of title | uid
filters (object, required) — includes / removes arrays of page titles
null
window.roamAlphaAPI.ui.filters.setPageLinkedRefsFilters(
{page: {title: "test"},
filters: {includes: ["Author"]}})
// resolves to null
roamAlphaAPI.ui.filters.getSidebarWindowFilters
window (object, required) — see sidebar window argument; "search-query" windows don't support filters
{"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) — see sidebar window argument; "search-query" windows don't support filters
filters (object, required) — includes / removes arrays of page titles
null
window.roamAlphaAPI.ui.filters.setSidebarWindowFilters(
{window: {"block-uid": "WYlc2nIO9", type: "outline"},
filters: {includes: ["Author"]}})
// resolves to null
roamAlphaAPI.ui.commandPalette
roamAlphaAPI.ui.commandPalette.addCommand
cmd-p). Calling again with the same label updates the existing command instead of adding a second one.
label (string, required) — text shown in the Command Palette. Prefix it with your plugin name for global uniqueness, e.g. "RoamRS: Start review session"
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. Without it (and unless 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 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) — called with the context object when the user selects the command. Return a string to insert at the current location, or null to handle insertion yourself (the typed search string is not removed).
{"block-uid": "YnatnbZzF",
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021",
indexes: [1, 10]}
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 addCommand
null
roamAlphaAPI.ui.blockContextMenu
addCommand again with the same label updates the existing command.
addCommand/removeCommand API and are documented below by their differences: pageContextMenu, pageRefContextMenu, blockRefContextMenu, pageLinkContextMenu, msContextMenu.
roamAlphaAPI.ui.blockContextMenu.addCommand
label (string, required) — text shown in the menu. Prefix it with your plugin name for global uniqueness, e.g. "RoamRS: Start review session"
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) — called with the block context when the user selects the command
{"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.pageContextMenu
addCommand/removeCommand API as ui.blockContextMenu, but both return null (synchronous).
display-conditional and callback:
{"page-uid": "YnatnbZzF",
"page-title": "title",
"window-id": "BBG4fFwolaVlT5FZQdzAI7P40aB3-body-outline-04-15-2021"}
roamAlphaAPI.ui.pageContextMenu.addCommand(
{label: "Debug: Console Log", callback: (e) => console.log(e)})
// => null
roamAlphaAPI.ui.pageRefContextMenu
ui.blockContextMenu; addCommand/removeCommand return null (synchronous).
display-conditional and callback:
{"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]])
roamAlphaAPI.ui.blockRefContextMenu
ui.blockContextMenu; addCommand/removeCommand return null (synchronous).
display-conditional and callback:
{"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
roamAlphaAPI.ui.pageLinkContextMenu
ui.blockContextMenu; addCommand/removeCommand return null (synchronous).
display-conditional and callback:
{"page-uid": "YnatnbZzF",
"page-title": "title"}
roamAlphaAPI.ui.msContextMenu
ui.blockContextMenu; addCommand/removeCommand return null (synchronous).
window.roamAlphaAPI.ui.msContextMenu.addCommand(
{label: "test", callback: () => { console.log("hey") }})
window.roamAlphaAPI.ui.msContextMenu.removeCommand({label: "test"})
// each => null
roamAlphaAPI.ui.multiselect
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
roamAlphaAPI.ui.individualMultiselect.getSelectedUids
cmd-m). Synchronous.
window.roamAlphaAPI.ui.individualMultiselect.getSelectedUids()
// => ["Vfht187T1", "abc123xyz"]
roamAlphaAPI.ui.graphView
roamAlphaAPI.ui.graphView.addCallback
graphView.wholeGraph below.
label (string, required) — used to upsert or remove the callback
callback (function, required) — called with {cytoscape, elements, type}:
cytoscape — the Cytoscape graph object
elements — array of the nodes and edges in the graph
type — "page" | "all-pages"
{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, optional) — only trigger for "page" or "all-pages" graph views; if omitted, triggers for both
null
roamAlphaAPI.ui.graphView.removeCallback
label.
label (string, required)
null
roamAlphaAPI.ui.graphView.wholeGraph
graphView.addCallback does not fire for it). Synchronous functions.
roamAlphaAPI.ui.graphView.wholeGraph.setMode
roamAlphaAPI.ui.graphView.wholeGraph.setExplorePages
roamAlphaAPI.ui.graphView.wholeGraph.getExplorePages
roamAlphaAPI.ui.graphView.wholeGraph.addCallback
label (string, required)
callback (function, required)
roamAlphaAPI.ui.graphView.wholeGraph.removeCallback
label.
label (string, required)
roamAlphaAPI.ui.graphView.wholeGraph.addCallback({
label: "test",
callback: (x) => console.log(x)})
roamAlphaAPI.ui.graphView.wholeGraph.removeCallback({label: "test"});
roamAlphaAPI.ui.graphView.wholeGraph.setExplorePages(["a"]);
roamAlphaAPI.ui.graphView.wholeGraph.getExplorePages();
// => ["a"]
roamAlphaAPI.ui.graphView.wholeGraph.setMode("Whole Graph");
roamAlphaAPI.ui.graphView.wholeGraph.setMode("Explore");
roamAlphaAPI.ui.components
unmountNode.
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?) — the path is compacted to a clickable ... 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
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
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
roamAlphaAPI.ui.react
ui.components. Note the props are camelCase, unlike the kebab-case keys of ui.components.
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 — uid and daily-note date helpers. All synchronous, all taking positional arguments.
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.dateToPageTitle
date (Date, required) — a JavaScript Date
roamAlphaAPI.util.dateToPageUid
generateUID when programmatically creating a daily note page and you need its uid ahead of time.
date (Date, required) — a JavaScript Date
roamAlphaAPI.file — upload, fetch, and delete files hosted on Roam
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
await roamAlphaAPI.file.upload({file: new File([""], "test"), toast: {hide: true}})
// => "https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Fmy-graph%2FaB3xK9mP2.png?alt=media&token=..."
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 file.upload or from a block
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 file.upload or from a block
undefined
roamAlphaAPI.user — info about the current user
roamAlphaAPI.user.uid
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 — properties (not functions) describing the current graph
roamAlphaAPI.graph.name — the name of the current graph (string)
roamAlphaAPI.graph.type — "hosted" or "offline" (string)
roamAlphaAPI.graph.isEncrypted — whether the graph is encrypted (boolean)
roamAlphaAPI.platform — boolean properties (not functions) describing the client
roamAlphaAPI.platform.isDesktop — true in the Roam Desktop App
roamAlphaAPI.platform.isMobileApp — true in the Roam Mobile App
roamAlphaAPI.platform.isMobile — true on small screens; purely a screen-size check (media query max-width: 450px)
roamAlphaAPI.platform.isIOS — true on iPhone, iPad, or iPod
roamAlphaAPI.platform.isPC — true on a PC; useful for offering different shortcuts on PC vs Mac
roamAlphaAPI.platform.isTouchDevice — true on touch devices
roamAlphaAPI.depot — installed Roam Depot extensions
roamAlphaAPI.depot.getInstalledExtensions
{ext-id: ext-map}; version is "DEV" for developer-loaded extensions
{"ccc+ccc-roam-pdf-2":
{id: "ccc+ccc-roam-pdf-2",
name: "Roam PDF Highlighter 2",
enabled: false,
version: "1"},
...}
roamAlphaAPI.constants — useful 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)