Builder Guide
Headless application guide and copy/paste kit
Build a custom frontend over BuildWithHQ authentication, scoped APIs, first-class modules, Inbox, Workflow, Files and exact server-side authorization.
A headless BuildWithHQ application replaces the native page presentation with your own React, Vue, mobile, desktop, or server-rendered interface. It does not replace authentication, tenant routing, DataRoles, Locations, stored-procedure contracts, audit, rate limits, files, Workflow, Inbox, or AI authorization.
This guide is generated from the same catalog as the native React kit: 23 capabilities, 166 page-module routes, and 47 additional tenant/Design routes. It does not invent a second backend.
1. Choose the correct headless boundary
| Caller | Use | Do not do |
|---|---|---|
| Custom tenant browser UI | The current same-origin tenant session plus the typed tenant APIs cataloged below. | Do not store the access token in localStorage or submit tenant/database identity as authorization. |
| External server or integration | The published Developer Platform, app-bound credentials, generated OpenAPI and versioned gateway routes. | Do not place server API keys in browser/mobile bundles or call internal tenant routes as an unauthenticated proxy. |
| Custom appliance service | A declared installed-service endpoint with reviewed egress, secret references, action permissions and correlation. | Do not expose provider credentials, unrestricted SQL or tenant infrastructure to the frontend. |
The generated transport below intentionally accepts only same-origin /api/ paths. If the frontend runs on another origin, use the published Developer API contract and its supported authentication/CORS boundary; do not weaken this check.
2. Copy the same-origin transport
The transport adds the current in-memory bearer token, delegates unsafe-method CSRF handling to the existing security helper, assigns a correlation ID, preserves server-side status/code/error/correlation details, clears local session state on 401, and never accepts a database name.
export type HeadlessMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
export interface HeadlessRequest {
readonly method?: HeadlessMethod;
readonly body?: unknown;
readonly signal?: AbortSignal;
readonly headers?: Readonly<Record<string, string>>;
}
export interface HeadlessTransportOptions {
readonly accessToken: () => string | null | undefined;
readonly fetchImplementation?: typeof fetch;
readonly applyCsrfHeader?: (headers: Headers, method: string) => void;
readonly onUnauthorized?: () => void;
}
export interface HeadlessTransport {
request<T>(path: string, request?: HeadlessRequest): Promise<T>;
}
export class HeadlessApiError extends Error {
public constructor(
message: string,
public readonly status: number,
public readonly code: string,
public readonly correlationId?: string,
public readonly retryAfterSeconds?: number,
) { super(message); this.name = "HeadlessApiError"; }
}
const sameOriginApiPath = (path: string): string => {
if (!path.startsWith("/api/") || path.includes("://") || path.includes("#") || path.length > 4000) {
throw new TypeError("Headless tenant requests require a bounded same-origin /api/ path.");
}
return path;
};
const readProblem = async (response: Response): Promise<HeadlessApiError> => {
let body: Record<string, unknown> = {};
try { body = await response.json() as Record<string, unknown>; } catch { /* safe fallback below */ }
const retryHeader = Number(response.headers.get("Retry-After"));
const retryBody = Number(body.retryAfterSeconds);
const retryAfterSeconds = Number.isFinite(retryBody) ? retryBody : Number.isFinite(retryHeader) ? retryHeader : undefined;
return new HeadlessApiError(
typeof body.error === "string" ? body.error : `Request failed (${response.status}).`,
response.status,
typeof body.code === "string" ? body.code : "request_failed",
typeof body.correlationId === "string" ? body.correlationId : response.headers.get("X-Correlation-ID") ?? undefined,
retryAfterSeconds,
);
};
export const createSameOriginHeadlessTransport = (options: HeadlessTransportOptions): HeadlessTransport => {
const fetchImplementation = options.fetchImplementation ?? globalThis.fetch;
if (!fetchImplementation) throw new TypeError("A fetch implementation is required.");
return {
async request<T>(path: string, request: HeadlessRequest = {}): Promise<T> {
const method = request.method ?? "GET";
const headers = new Headers({ Accept: "application/json", ...request.headers });
const token = options.accessToken();
if (!token) { options.onUnauthorized?.(); throw new HeadlessApiError("Sign in before loading tenant data.", 401, "tenant_session_required"); }
headers.set("Authorization", `Bearer ${token}`);
headers.set("X-Correlation-ID", crypto.randomUUID());
if (request.body !== undefined) headers.set("Content-Type", "application/json");
options.applyCsrfHeader?.(headers, method);
const response = await fetchImplementation(sameOriginApiPath(path), {
method,
credentials: "same-origin",
headers,
body: request.body === undefined ? undefined : JSON.stringify(request.body),
signal: request.signal,
});
if (response.status === 401) options.onUnauthorized?.();
if (!response.ok) throw await readProblem(response);
if (response.status === 204) return undefined as T;
return await response.json() as T;
},
};
};
/* In apps/tenant-runtime, inject getTenantAccessToken, applyCsrfHeader and
clearTenantSession. Keep refresh/session rotation in the official auth client. */
Wire it to the official tenant session
import { clearTenantSession, getTenantAccessToken } from "./api";
import { applyCsrfHeader } from "./webSecurity";
import { createSameOriginHeadlessTransport } from "./HeadlessTransport";
export const transport = createSameOriginHeadlessTransport({
accessToken: getTenantAccessToken,
applyCsrfHeader,
onUnauthorized: clearTenantSession,
});
// Keep login, refresh rotation, logout and session restore in the official
// tenant auth client. The custom component consumes only this transport.
Let the existing login/refresh client own refresh-cookie rotation and session restore. A 401 should return the app to its sign-in state; a 403 is an authorization denial, 404 keeps absent and foreign identifiers indistinguishable, 409 requires reloading stale state, and 429 requires honoring the retry window.
3. Working, paginated read/write example
This example requests exactly one 25-row page from /api/modules/contacts, parses the response through parseContactList, creates through the reviewed POST contract, validates the receipt with parseContactMutation, aborts obsolete reads, and never fetches a full table to filter in React.
import { useEffect, useState, type FormEvent } from "react";
import {
contactsModule,
parseContactList,
parseContactMutation,
type ContactList,
} from "@buildwithhq/module-sdk";
import type { HeadlessTransport } from "./HeadlessTransport";
export interface HeadlessContactsExampleProps {
readonly transport: HeadlessTransport;
readonly styled?: boolean;
}
export const HeadlessContactsExample = ({ transport, styled = false }: HeadlessContactsExampleProps) => {
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
const [result, setResult] = useState<ContactList>();
const [error, setError] = useState<string>();
const [refresh, setRefresh] = useState(0);
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
useEffect(() => {
const controller = new AbortController();
const query = new URLSearchParams({ pageNumber: String(page), pageSize: "25" });
if (search.trim()) query.set("search", search.trim());
setError(undefined);
void transport.request<unknown>(`${contactsModule.apiBasePath}?${query}`, { signal: controller.signal })
.then((value) => setResult(parseContactList(value)))
.catch((failure: unknown) => { if (!controller.signal.aborted) setError(failure instanceof Error ? failure.message : "Contacts unavailable."); });
return () => controller.abort();
}, [page, refresh, search, transport]);
const create = async (event: FormEvent) => {
event.preventDefault(); setError(undefined);
try {
const value = await transport.request<unknown>(contactsModule.apiBasePath, {
method: "POST", body: { firstName, lastName, email },
});
parseContactMutation(value);
setFirstName(""); setLastName(""); setEmail(""); setPage(1); setRefresh((value) => value + 1);
} catch (failure) { setError(failure instanceof Error ? failure.message : "Contact could not be created."); }
};
return <section className={styled ? "bwhq-headless-resource" : undefined}>
<header><div><p>Headless first-class module</p><h2>Contacts</h2></div><label>Search visible contacts<input type="search" value={search} onChange={(event) => { setSearch(event.target.value); setPage(1); }} /></label></header>
{error && <p role="alert">{error}</p>}
{!result && !error && <p role="status">Loading contacts…</p>}
{result && <><ul>{result.items.map((contact) => <li key={contact.recordId}><strong>{contact.title}</strong><span>{contact.email || contact.companyName || "No secondary value"}</span></li>)}</ul><nav aria-label="Contact pages"><button disabled={page <= 1} onClick={() => setPage((value) => value - 1)} type="button">Previous</button><span>Page {result.pageNumber} of {Math.max(1, result.totalPages)}</span><button disabled={page >= result.totalPages} onClick={() => setPage((value) => value + 1)} type="button">Next</button></nav></>}
<form onSubmit={(event) => void create(event)}><h3>Create a contact</h3><label>First name<input value={firstName} onChange={(event) => setFirstName(event.target.value)} /></label><label>Last name<input value={lastName} onChange={(event) => setLastName(event.target.value)} /></label><label>Email<input type="email" value={email} onChange={(event) => setEmail(event.target.value)} /></label><button type="submit">Create contact</button></form>
</section>;
};
Use it
import { HeadlessContactsExample } from "./HeadlessContactsExample";
import { transport } from "./transport";
export const ContactsPage = () => (
<HeadlessContactsExample transport={transport} styled />
);
Copy the pattern, not the Contacts field names: bounded query parameters, unknown JSON at the transport boundary, official SDK parser, server pagination, explicit loading/empty/error states, and one narrow mutation receipt.
4. Headless data bindings
For custom page-shaped projections, request a reviewed binding key. The server resolves it to an approved sp_ds_* contract and applies the signed-in identity. The client does not send SQL, a procedure name, a SaaS ID, or a database selector.
import { parseRuntimeDataBinding } from "@buildwithhq/page-runtime";
import { transport } from "./transport";
export const loadOpenWork = async (signal: AbortSignal) => {
const bindingKey = "work.open";
const raw = await transport.request<unknown>(
`/api/runtime/data/${encodeURIComponent(bindingKey)}`,
{ signal },
);
return parseRuntimeDataBinding(raw, bindingKey).data;
};
5. Universal Inbox, support tickets and GoClaw
The official package exposes typed clients independently from its native UI. A headless component can consume those clients for bounded queues, ticket-only views, badge/notifications, email ticketing settings, human state, Workflow decisions and GoClaw review work. Use the native components when you want the complete lifecycle without reimplementing every control.
import {
createApprovalQueueHttpClient,
createUniversalInboxHttpClient,
} from "@buildwithhq/universal-inbox";
import { ensureCsrfToken } from "./webSecurity";
import { getTenantAccessToken } from "./api";
import {
HeadlessApprovalQueueStarter,
HeadlessInboxQueueStarter,
} from "./UniversalInboxStarters";
const inboxClient = createUniversalInboxHttpClient({
accessToken: getTenantAccessToken,
csrfToken: ensureCsrfToken,
});
const approvalClient = createApprovalQueueHttpClient({
accessToken: getTenantAccessToken,
csrfToken: ensureCsrfToken,
});
export const SupportQueue = () => (
<HeadlessInboxQueueStarter client={inboxClient} ticketingOnly styled />
);
export const AiReviewQueue = () => (
<HeadlessApprovalQueueStarter client={approvalClient} styled />
);
Copy all native and headless Inbox/GoClaw starters
import { useEffect, useState } from "react";
import {
GoClawApprovalQueue,
UniversalInbox,
type ApprovalQueueClient,
type ApprovalQueueItem,
type InboxQueueItem,
type UniversalInboxClient,
} from "@buildwithhq/universal-inbox";
interface InboxStarterProps {
readonly client: UniversalInboxClient;
readonly ticketingOnly?: boolean;
readonly assignedToMe?: boolean;
readonly onOpen?: (inboxItemId: string) => void;
readonly styled?: boolean;
}
export const HeadlessInboxQueueStarter = ({ client, ticketingOnly, assignedToMe, onOpen, styled = false }: InboxStarterProps) => {
const [items, setItems] = useState<readonly InboxQueueItem[]>([]);
const [error, setError] = useState<string>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
setLoading(true); setError(undefined);
void client.list({ ticketingOnly, assignedToMe, topN: 100 }, controller.signal)
.then(setItems)
.catch((failure: unknown) => { if (!controller.signal.aborted) setError(failure instanceof Error ? failure.message : "Inbox unavailable."); })
.finally(() => { if (!controller.signal.aborted) setLoading(false); });
return () => controller.abort();
}, [assignedToMe, client, ticketingOnly]);
return <section aria-busy={loading} className={styled ? "bwhq-headless-list" : undefined}>
<h2>{ticketingOnly ? "Support tickets" : "Universal Inbox"}</h2>
{loading && <p role="status">Loading inbox…</p>}
{error && <p role="alert">{error}</p>}
{!loading && !error && items.length === 0 && <p>No visible work.</p>}
<ul>{items.map((item) => <li key={item.inboxItemId}><button type="button" onClick={() => onOpen?.(item.inboxItemId)}><strong>{item.ticket?.key ? item.ticket.key + " · " : ""}{item.subject || item.source.sourceType}</strong><span>{item.status} · {item.previewText || "No preview"}</span></button></li>)}</ul>
</section>;
};
interface ApprovalStarterProps {
readonly client: ApprovalQueueClient;
readonly onOpen?: (item: ApprovalQueueItem) => void;
readonly styled?: boolean;
}
export const HeadlessApprovalQueueStarter = ({ client, onOpen, styled = false }: ApprovalStarterProps) => {
const [items, setItems] = useState<readonly ApprovalQueueItem[]>([]);
const [error, setError] = useState<string>();
useEffect(() => {
const controller = new AbortController();
void client.list(100, controller.signal).then(setItems)
.catch((failure: unknown) => { if (!controller.signal.aborted) setError(failure instanceof Error ? failure.message : "Approval queue unavailable."); });
return () => controller.abort();
}, [client]);
return <section className={styled ? "bwhq-headless-list" : undefined}>
<h2>GoClaw approval work</h2>{error && <p role="alert">{error}</p>}
<ul>{items.map((item) => <li key={item.suggestionBatchId}><button type="button" onClick={() => onOpen?.(item)}><strong>{item.subject || item.summary || item.sourceType}</strong><span>{item.batchStatus}{item.isStale ? " · stale" : ""}</span></button></li>)}</ul>
</section>;
};
/* These two exports preserve the complete native behaviors. The bare export adds
no wrapper CSS, but the native package intentionally ships its own module CSS. */
export const BareNativeUniversalInbox = (props: { readonly client: UniversalInboxClient; readonly initialInboxItemId?: string }) =>
<UniversalInbox {...props} />;
export const FramedNativeUniversalInbox = (props: { readonly client: UniversalInboxClient; readonly initialInboxItemId?: string }) =>
<div className="bwhq-native-frame"><UniversalInbox {...props} /></div>;
export const BareNativeGoClawApprovalQueue = (props: { readonly client: ApprovalQueueClient }) =>
<GoClawApprovalQueue {...props} />;
export const FramedNativeGoClawApprovalQueue = (props: { readonly client: ApprovalQueueClient }) =>
<div className="bwhq-native-frame"><GoClawApprovalQueue {...props} /></div>;The headless list starters demonstrate reads and selection. They do not silently implement ticket resolution, proof/file handling, Workflow approval, GoClaw edits or delivery retry. Call the corresponding typed client method only from an explicit UI action and preserve ActivityVersion/stale-state inputs.
6. Menus and the custom workspace shell
Use the server-returned User Type menu as route eligibility, then render it in your design. Menu visibility is not record permission. The current shell starter stays left aligned and expands the center while allowing an optional 280px context panel.
import { BuildWithHQMenu } from "./BuildWithHQMenu";
import { StyledTenantWorkspaceShell } from "./TenantWorkspaceShell";
export const AppShell = ({ menu, pageKey, children }) => (
<StyledTenantWorkspaceShell
applicationName="Your SaaS"
pageTitle="Workspace"
menu={<BuildWithHQMenu
items={menu}
activePageKey={pageKey}
resolvePageHref={(key) => `/?page=${encodeURIComponent(key)}`}
styled
/>}
contextPanel={<p>Page-specific context belongs here.</p>}
>
{children}
</StyledTenantWorkspaceShell>
);
Copy the complete menu component
import type { ReactNode } from "react";
export interface BuildWithHQMenuItem {
readonly id: string;
readonly parentId?: string | null;
readonly label: string;
readonly iconKey?: string | null;
readonly targetType: "Page" | "Group" | "Module" | "External";
readonly pageKey?: string | null;
readonly url?: string | null;
readonly sortOrder: number;
}
export interface BuildWithHQMenuProps {
readonly items: readonly BuildWithHQMenuItem[];
readonly activePageKey?: string;
readonly resolvePageHref: (pageKey: string) => string;
readonly icon?: (iconKey: string) => ReactNode;
readonly styled?: boolean;
}
const safeExternalUrl = (value: string | null | undefined): string | undefined => {
if (!value || value.length > 2000) return undefined;
try {
const url = new URL(value);
return url.protocol === "https:" && !url.username && !url.password ? url.toString() : undefined;
} catch { return undefined; }
};
export const BuildWithHQMenu = ({ items, activePageKey, resolvePageHref, icon, styled = false }: BuildWithHQMenuProps) => {
const roots = items.filter((item) => !item.parentId).sort((left, right) => left.sortOrder - right.sortOrder);
const renderItem = (item: BuildWithHQMenuItem): ReactNode => {
const children = items.filter((candidate) => candidate.parentId === item.id).sort((left, right) => left.sortOrder - right.sortOrder);
if (item.targetType === "Group") return <li key={item.id}><span>{item.iconKey && icon?.(item.iconKey)}{item.label}</span>{children.length > 0 && <ul>{children.map(renderItem)}</ul>}</li>;
const href = item.targetType === "Page" && item.pageKey ? resolvePageHref(item.pageKey)
: item.targetType === "External" ? safeExternalUrl(item.url) : undefined;
return <li key={item.id}>{href ? <a href={href} aria-current={item.pageKey === activePageKey ? "page" : undefined}>{item.iconKey && icon?.(item.iconKey)}{item.label}</a> : <span aria-disabled="true">{item.label}</span>}</li>;
};
return <nav aria-label="Application" className={styled ? "bwhq-app-menu" : undefined}><ul>{roots.map(renderItem)}</ul></nav>;
};Copy the complete workspace shell
import type { ReactNode } from "react";
export interface TenantWorkspaceShellProps {
readonly applicationName: string;
readonly pageTitle: string;
readonly menu: ReactNode;
readonly children: ReactNode;
readonly headerActions?: ReactNode;
readonly contextPanel?: ReactNode;
readonly styled?: boolean;
}
const TenantWorkspaceShellBody = ({ applicationName, pageTitle, menu, children, headerActions, contextPanel, styled = false }: TenantWorkspaceShellProps) => (
<div className={styled ? "bwhq-workspace" : undefined}>
<header className={styled ? "bwhq-workspace__header" : undefined}>
<div><p>{applicationName}</p><h1>{pageTitle}</h1></div>
{headerActions && <div aria-label="Page actions">{headerActions}</div>}
</header>
<div className={styled ? "bwhq-workspace__columns" : undefined}>
<aside aria-label="Application menu" className={styled ? "bwhq-workspace__menu" : undefined}>{menu}</aside>
<main className={styled ? "bwhq-workspace__main" : undefined}>{children}</main>
{contextPanel && <aside aria-label="Page context" className={styled ? "bwhq-workspace__context" : undefined}>{contextPanel}</aside>}
</div>
</div>
);
export const UnstyledTenantWorkspaceShell = (props: Omit<TenantWorkspaceShellProps, "styled">) =>
<TenantWorkspaceShellBody {...props} styled={false} />;
export const StyledTenantWorkspaceShell = (props: Omit<TenantWorkspaceShellProps, "styled">) =>
<TenantWorkspaceShellBody {...props} styled />;7. Files and binary responses
HeadlessTransport is intentionally JSON-only. For multipart upload and Blob download, reuse the current typed uploadFile, downloadFileContent, uploadTenantAsset, and loadTenantAssetContent functions or implement their exact reviewed contracts. Keep MIME/size validation, CSRF, unauthorized-download denial, malware scanning state, orphan cleanup and native File authorization intact.
8. Every capability and exact operation
Each section lists the current integration kind, page key where one exists, API roots, public package-client methods, exact HTTP routes, current browser function and response parser. A background capability with no interactive route is explicitly left without one rather than given an invented endpoint.
Universal Inbox 10 headless operations
Integration: shell-component · Native key: Not a page block
API roots: /api/inbox, /api/inbox/items
Typed client methods: list, get, badge, notifications, deliveryDebug, retryDelivery, setReadState, setStatus, setPriority, setAssignment, getEmailTicketingSettings, setEmailTicketing, decideWorkflowApproval
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/inbox/items | Use the typed transport/client | Use the returned typed contract |
GET/api/inbox/email-channels/ticketing | Use the typed transport/client | Use the returned typed contract |
PUT/api/inbox/email-channels/{channelConnectionId:guid}/ticketing | Use the typed transport/client | Use the returned typed contract |
GET/api/inbox/items/{inboxItemId:guid} | Use the typed transport/client | Use the returned typed contract |
GET/api/inbox/badge | Use the typed transport/client | Use the returned typed contract |
GET/api/inbox/notifications | Use the typed transport/client | Use the returned typed contract |
GET/api/inbox/delivery/debug | Use the typed transport/client | Use the returned typed contract |
POST/api/inbox/delivery/{outboundMessageId:guid}/retry | Use the typed transport/client | Use the returned typed contract |
PUT/api/inbox/items/{inboxItemId:guid}/human-state | Use the typed transport/client | Use the returned typed contract |
POST/api/inbox/items/{inboxItemId:guid}/workflow-approval | Use the typed transport/client | Use the returned typed contract |
Checklists & Signoffs 9 headless operations
Integration: page-module · Native key: module.checklists-signoffs
API roots: /api/modules/checklists-signoffs
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/checklists-signoffs/templates | listChecklistTemplates | parseChecklistTemplateList |
POST/api/modules/checklists-signoffs/templates | createChecklistTemplate | parseChecklistMutation |
GET/api/modules/checklists-signoffs/runs | listChecklistRuns | parseChecklistRunList |
GET/api/modules/checklists-signoffs/runs/{checklistRunId:guid} | getChecklistRun | parseChecklistRunDetail |
POST/api/modules/checklists-signoffs/runs | startChecklistRun | parseChecklistMutation |
PUT/api/modules/checklists-signoffs/items/{checklistRunItemId:guid} | updateChecklistItem | parseChecklistMutation |
POST/api/modules/checklists-signoffs/items/{checklistRunItemId:guid}/proof | attachChecklistProof | parseChecklistMutation |
DELETE/api/modules/checklists-signoffs/proof/{checklistItemEvidenceId:guid} | removeChecklistProof | parseChecklistMutation |
POST/api/modules/checklists-signoffs/runs/{checklistRunId:guid}/submit | submitChecklistForSignoff | parseChecklistMutation |
GoClaw virtual assistant 6 headless operations
Integration: shell-component · Native key: Not a page block
API roots: /api/goclaw/agents, /api/goclaw/approvals
Typed client methods: list, approve, reject, takeOver, retry
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
PUT/api/goclaw/agents/{goClawAgentId:guid}/authority | Use the typed transport/client | Use the returned typed contract |
GET/api/goclaw/approvals | Use the typed transport/client | Use the returned typed contract |
POST/api/goclaw/approvals/{suggestionBatchId:guid}/approve | Use the typed transport/client | Use the returned typed contract |
POST/api/goclaw/approvals/{suggestionBatchId:guid}/reject | Use the typed transport/client | Use the returned typed contract |
POST/api/goclaw/approvals/{suggestionBatchId:guid}/take-over | Use the typed transport/client | Use the returned typed contract |
POST/api/goclaw/approvals/{suggestionBatchId:guid}/retry | Use the typed transport/client | Use the returned typed contract |
AI Insights 0 headless operations
Integration: background-service · Native key: Not a page block
API roots: Background service contracts
This is a scheduled/background capability. Use its governed service and secured feed contracts when exposed; do not invent a browser mutation endpoint.
Contacts 5 headless operations
Integration: page-module · Native key: module.contacts
API roots: /api/modules/contacts
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/contacts | listContacts | parseContactList |
GET/api/modules/contacts/{recordId:guid} | getContact | parseContactDetail |
POST/api/modules/contacts | createContact | parseContactMutation |
PUT/api/modules/contacts/{recordId:guid} | updateContact | parseContactMutation |
PUT/api/modules/contacts/{recordId:guid}/favorite | setContactFavorite | parseContactMutation |
Work Orders 6 headless operations
Integration: page-module · Native key: module.work-orders
API roots: /api/modules/work-orders
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/work-orders | listWorkOrders | parseWorkOrderList |
GET/api/modules/work-orders/{recordId:guid} | getWorkOrder | parseWorkOrderDetail |
POST/api/modules/work-orders | createWorkOrder | parseWorkOrderMutation |
PUT/api/modules/work-orders/{recordId:guid} | updateWorkOrder | parseWorkOrderMutation |
PUT/api/modules/work-orders/{recordId:guid}/status | setWorkOrderStatus | parseWorkOrderMutation |
PUT/api/modules/work-orders/{recordId:guid}/assignment | assignWorkOrder | parseWorkOrderMutation |
Reservations 7 headless operations
Integration: page-module · Native key: module.reservations
API roots: /api/modules/reservations
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/reservations/products | listReservationProducts | parseReservationProductList |
POST/api/modules/reservations/products | saveReservationProduct | parseReservationMutation |
GET/api/modules/reservations | listReservations | parseReservationList |
GET/api/modules/reservations/{recordId:guid} | getReservation | parseReservationDetail |
POST/api/modules/reservations/purchase | purchaseReservation | parseReservationMutation |
PUT/api/modules/reservations/{recordId:guid}/status | setReservationStatus | parseReservationMutation |
PUT/api/modules/reservations/{recordId:guid}/followups | updateReservationFollowup | parseReservationMutation |
Calendar 5 headless operations
Integration: page-module · Native key: module.calendar
API roots: /api/modules/calendar
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/calendar | listCalendarEvents | parseCalendarEventList |
GET/api/modules/calendar/{recordId:guid} | getCalendarEvent | parseCalendarEventDetail |
POST/api/modules/calendar | createCalendarEvent | parseCalendarMutation |
PUT/api/modules/calendar/{recordId:guid} | updateCalendarEvent | parseCalendarMutation |
PUT/api/modules/calendar/{recordId:guid}/favorite | setCalendarFavorite | parseCalendarMutation |
Files & attachments 8 headless operations
Integration: page-module · Native key: module.files
API roots: /api/modules/files
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/files | listFiles | parseFileList |
GET/api/modules/files/{recordId:guid} | getFile | parseFileDetail |
POST/api/modules/files/upload | uploadFile | parseFileMutation |
PUT/api/modules/files/{recordId:guid} | updateFile | parseFileMutation |
POST/api/modules/files/{recordId:guid}/attachments | attachFile | parseFileMutation |
DELETE/api/modules/files/{recordId:guid}/attachments/{attachmentId:guid} | detachFile | parseFileMutation |
PUT/api/modules/files/{recordId:guid}/favorite | setFileFavorite | parseFileMutation |
GET/api/modules/files/{recordId:guid}/content | downloadFileContent | Use the returned typed contract |
Conversations & messages 7 headless operations
Integration: page-module · Native key: module.conversations
API roots: /api/modules/conversations
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/conversations | listConversations | parseConversationList |
GET/api/modules/conversations/{recordId:guid} | getConversation | parseConversationDetail |
POST/api/modules/conversations | createConversation | parseConversationMutation |
PUT/api/modules/conversations/{recordId:guid} | updateConversation | parseConversationMutation |
POST/api/modules/conversations/{recordId:guid}/messages | postConversationMessage | parseConversationMutation |
POST/api/modules/conversations/direct | Use the typed transport/client | Use the returned typed contract |
PUT/api/modules/conversations/{recordId:guid}/favorite | setConversationFavorite | parseConversationMutation |
Company news 5 headless operations
Integration: page-module · Native key: module.company-news
API roots: /api/modules/company-news
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/company-news | listCompanyNews | parseCompanyNewsList |
GET/api/modules/company-news/{recordId:guid} | getCompanyNews | parseCompanyNewsDetail |
POST/api/modules/company-news | createCompanyNews | parseCompanyNewsMutation |
PUT/api/modules/company-news/{recordId:guid} | updateCompanyNews | parseCompanyNewsMutation |
PUT/api/modules/company-news/{recordId:guid}/favorite | setCompanyNewsFavorite | parseCompanyNewsMutation |
Knowledge Core 37 headless operations
Integration: page-module · Native key: module.knowledge-articles
API roots: /api/modules/knowledge-articles, /api/modules/knowledge-core
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/knowledge-articles | listKnowledgeArticles | parseKnowledgeArticlesList |
GET/api/modules/knowledge-articles/{recordId:guid} | getKnowledgeArticle | parseKnowledgeArticleDetail |
POST/api/modules/knowledge-articles | createKnowledgeArticle | parseKnowledgeArticleMutation |
PUT/api/modules/knowledge-articles/{recordId:guid} | updateKnowledgeArticle | parseKnowledgeArticleMutation |
PUT/api/modules/knowledge-articles/{recordId:guid}/favorite | setKnowledgeArticleFavorite | parseKnowledgeArticleMutation |
GET/api/modules/knowledge-core | listKnowledgeCore | parseKnowledgeCoreList |
GET/api/modules/knowledge-core/{recordId:guid} | getKnowledgeCore | parseKnowledgeCoreDetail |
POST/api/modules/knowledge-core | createKnowledgeCore | parseKnowledgeCoreMutation |
PUT/api/modules/knowledge-core/{recordId:guid} | updateKnowledgeCore | parseKnowledgeCoreMutation |
POST/api/modules/knowledge-core/{recordId:guid}/publish | publishKnowledgeCore | parseKnowledgeCoreMutation |
POST/api/modules/knowledge-core/{recordId:guid}/archive | archiveKnowledgeCore | parseKnowledgeCoreMutation |
GET/api/modules/knowledge-core/{recordId:guid}/revisions | getKnowledgeCoreRevisions | parseKnowledgeRevisions |
POST/api/modules/knowledge-core/{recordId:guid}/restore | Use the typed transport/client | Use the returned typed contract |
GET/api/modules/knowledge-core/collections | listKnowledgeCoreCollections | parseKnowledgeCollections |
POST/api/modules/knowledge-core/collections | Use the typed transport/client | Use the returned typed contract |
PUT/api/modules/knowledge-core/collections/{collectionId:guid} | Use the typed transport/client | Use the returned typed contract |
POST/api/modules/knowledge-core/collections/{collectionId:guid}/items/{recordId:guid} | Use the typed transport/client | Use the returned typed contract |
DELETE/api/modules/knowledge-core/collections/{collectionId:guid}/items/{recordId:guid} | Use the typed transport/client | Use the returned typed contract |
GET/api/modules/knowledge-core/{recordId:guid}/owners | getKnowledgeCoreOwners | parseKnowledgeOwners |
POST/api/modules/knowledge-core/{recordId:guid}/owners | Use the typed transport/client | Use the returned typed contract |
DELETE/api/modules/knowledge-core/owners/{knowledgeOwnerId:guid} | Use the typed transport/client | Use the returned typed contract |
GET/api/modules/knowledge-core/unowned | Use the typed transport/client | Use the returned typed contract |
GET/api/modules/knowledge-core/reviews | listKnowledgeReviews | parseKnowledgeReviews |
POST/api/modules/knowledge-core/reviews/{reviewCycleId:guid}/begin | beginKnowledgeReview | parseKnowledgeReviewMutation |
POST/api/modules/knowledge-core/reviews/{reviewCycleId:guid}/complete | completeKnowledgeReview | parseKnowledgeReviewMutation |
POST/api/modules/knowledge-core/reviews/{reviewCycleId:guid}/reassign | reassignKnowledgeReview | parseKnowledgeReviewMutation |
GET/api/modules/knowledge-core/health | getKnowledgeHealth | parseKnowledgeHealth |
GET/api/modules/knowledge-core/questions | listKnowledgeQuestions | parseKnowledgeQuestions |
POST/api/modules/knowledge-core/questions | createKnowledgeQuestion | parseKnowledgeQuestionMutation |
POST/api/modules/knowledge-core/questions/{knowledgeQuestionId:guid}/assign | assignKnowledgeQuestion | parseKnowledgeQuestionMutation |
POST/api/modules/knowledge-core/questions/{knowledgeQuestionId:guid}/answer | answerKnowledgeQuestion | parseKnowledgeQuestionMutation |
POST/api/modules/knowledge-core/questions/{knowledgeQuestionId:guid}/convert | convertKnowledgeQuestion | parseKnowledgeQuestionMutation |
POST/api/modules/knowledge-core/{recordId:guid}/feedback | recordKnowledgeFeedback | parseKnowledgeFeedbackMutation |
GET/api/modules/knowledge-core/{recordId:guid}/feedback | getKnowledgeFeedback | parseKnowledgeFeedbackSummary |
GET/api/modules/knowledge-core/gaps | getKnowledgeGaps | parseKnowledgeGaps |
GET/api/modules/knowledge-core/support-learning/candidates | Use the typed transport/client | Use the returned typed contract |
POST/api/modules/knowledge-core/support-learning/candidates | Use the typed transport/client | Use the returned typed contract |
Web links 5 headless operations
Integration: page-module · Native key: module.web-links
API roots: /api/modules/web-links
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/web-links | listWebLinks | parseWebLinksList |
GET/api/modules/web-links/{recordId:guid} | getWebLink | parseWebLinkDetail |
POST/api/modules/web-links | createWebLink | parseWebLinkMutation |
PUT/api/modules/web-links/{recordId:guid} | updateWebLink | parseWebLinkMutation |
PUT/api/modules/web-links/{recordId:guid}/favorite | setWebLinkFavorite | parseWebLinkMutation |
Chat rooms 9 headless operations
Integration: page-module · Native key: module.chat-rooms
API roots: /api/modules/chat-rooms
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/chat-rooms | listChatRooms | parseChatRoomsList |
GET/api/modules/chat-rooms/{recordId:guid} | getChatRoom | parseChatRoomDetail |
POST/api/modules/chat-rooms | createChatRoom | parseChatRoomMutation |
PUT/api/modules/chat-rooms/{recordId:guid} | updateChatRoom | parseChatRoomMutation |
POST/api/modules/chat-rooms/{recordId:guid}/messages | postChatMessage | parseChatRoomMutation |
PUT/api/modules/chat-rooms/{recordId:guid}/messages/{chatMessageId:guid}/reaction | setChatReaction | parseChatRoomMutation |
PUT/api/modules/chat-rooms/{recordId:guid}/members/{memberUserId:guid} | setChatRoomMember | parseChatRoomMutation |
PUT/api/modules/chat-rooms/{recordId:guid}/read | markChatRoomRead | parseChatRoomMutation |
PUT/api/modules/chat-rooms/{recordId:guid}/favorite | setChatRoomFavorite | parseChatRoomMutation |
Discussion boards 10 headless operations
Integration: page-module · Native key: module.discussion-boards
API roots: /api/modules/discussion-boards
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/discussion-boards | listDiscussionBoards | parseDiscussionBoardsList |
GET/api/modules/discussion-boards/{recordId:guid} | getDiscussionBoard | parseDiscussionBoardDetail |
POST/api/modules/discussion-boards | createDiscussionBoard | parseDiscussionMutation |
PUT/api/modules/discussion-boards/{recordId:guid} | updateDiscussionBoard | parseDiscussionMutation |
POST/api/modules/discussion-boards/{boardRecordId:guid}/topics | createDiscussionTopic | parseDiscussionMutation |
GET/api/modules/discussion-boards/topics/{recordId:guid} | getDiscussionTopic | parseDiscussionTopicDetail |
PUT/api/modules/discussion-boards/topics/{recordId:guid} | updateDiscussionTopic | parseDiscussionMutation |
POST/api/modules/discussion-boards/topics/{topicRecordId:guid}/posts | postDiscussionReply | parseDiscussionMutation |
PUT/api/modules/discussion-boards/posts/{recordId:guid} | updateDiscussionPost | parseDiscussionMutation |
PUT/api/modules/discussion-boards/records/{recordId:guid}/favorite | setDiscussionFavorite | parseDiscussionMutation |
Mail reader 4 headless operations
Integration: page-module · Native key: module.mail-reader
API roots: /api/modules/mail-reader
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/mail-reader | listMailReaderMessages | parseMailReaderList |
GET/api/modules/mail-reader/{recordId:guid} | getMailReaderMessage | parseMailReaderDetail |
PUT/api/modules/mail-reader/{recordId:guid}/read | setMailReaderRead | parseMailReaderMutation |
PUT/api/modules/mail-reader/{recordId:guid}/favorite | setMailReaderFavorite | parseMailReaderMutation |
Favorites 4 headless operations
Integration: page-module · Native key: module.favorites
API roots: /api/modules/favorites
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/favorites | listFavorites | parseFavoritesList |
GET/api/modules/favorites/{recordId:guid} | getFavorite | parseFavoriteDetail |
PUT/api/modules/favorites/{recordId:guid}/favorite | setFavorite | parseFavoriteMutation |
PUT/api/modules/favorites/{recordId:guid}/preferences | updateFavoritePreferences | parseFavoriteMutation |
Notifications 4 headless operations
Integration: page-module · Native key: module.notifications
API roots: /api/modules/notifications
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/notifications | listNotifications | parseNotificationList |
GET/api/modules/notifications/{notificationId:guid} | getNotification | parseNotificationDetail |
PUT/api/modules/notifications/{notificationId:guid}/state | setNotificationState | parseNotificationMutation |
PUT/api/modules/notifications/{notificationId:guid}/source-favorite | setNotificationSourceFavorite | parseNotificationMutation |
Dynamic/custom records 6 headless operations
Integration: page-module · Native key: module.dynamic-records
API roots: /api/modules/dynamic
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/dynamic/{moduleKey}/schema | getDynamicModuleSchema | parseDynamicModuleSchema |
GET/api/modules/dynamic/{moduleKey} | listDynamicModuleRecords | parseDynamicModuleList |
GET/api/modules/dynamic/{moduleKey}/{recordId:guid} | getDynamicModuleRecord | parseDynamicModuleDetail |
POST/api/modules/dynamic/{moduleKey} | createDynamicModuleRecord | parseDynamicModuleMutation |
PUT/api/modules/dynamic/{moduleKey}/{recordId:guid} | updateDynamicModuleRecord | parseDynamicModuleMutation |
PUT/api/modules/dynamic/{moduleKey}/{recordId:guid}/favorite | setDynamicModuleFavorite | parseDynamicModuleMutation |
ActiveWorkplace 11 headless operations
Integration: page-module · Native key: module.active-workplace
API roots: /api/modules/active-workplace
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/active-workplace | listActiveWorkplaces | parseActiveWorkplaceList |
POST/api/modules/active-workplace | createActiveWorkplace | parseActiveWorkplaceMutation |
GET/api/modules/active-workplace/{activeWorkplaceId:guid} | getActiveWorkplace | parseActiveWorkplaceDetail |
PATCH/api/modules/active-workplace/{activeWorkplaceId:guid} | updateActiveWorkplace | parseActiveWorkplaceMutation |
POST/api/modules/active-workplace/{activeWorkplaceId:guid}/status | setActiveWorkplaceStatus | parseActiveWorkplaceMutation |
GET/api/modules/active-workplace/{activeWorkplaceId:guid}/participants/catalog | getActiveWorkplaceParticipantCatalog | parseActiveWorkplaceCatalog |
POST/api/modules/active-workplace/{activeWorkplaceId:guid}/participants | addActiveWorkplaceParticipant | parseActiveWorkplaceMutation |
DELETE/api/modules/active-workplace/{activeWorkplaceId:guid}/participants/{activeWorkplaceParticipantId:guid} | removeActiveWorkplaceParticipant | parseActiveWorkplaceMutation |
POST/api/modules/active-workplace/{activeWorkplaceId:guid}/activity | recordActiveWorkplaceActivity | parseActiveWorkplaceMutation |
POST/api/modules/active-workplace/{activeWorkplaceId:guid}/graph/refresh | refreshActiveWorkplaceGraph | parseActiveWorkplaceMutation |
GET/api/modules/active-workplace/{activeWorkplaceId:guid}/playback | getActiveWorkplacePlayback | parseActiveWorkplacePlayback |
Record relations 9 headless operations
Integration: page-module · Native key: module.record-graph
API roots: /api/modules/record-graph
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/record-graph/records | searchRecordGraph | parseRecordGraphSearch |
GET/api/modules/record-graph/{recordId:guid} | getRecordGraph | parseRecordGraph |
PUT/api/modules/record-graph/{recordId:guid}/relations | addRecordGraphRelation | parseRecordGraphMutation |
DELETE/api/modules/record-graph/relations/{recordRelationId:guid} | removeRecordGraphRelation | parseRecordGraphMutation |
PUT/api/modules/record-graph/{recordId:guid}/favorite | setRecordGraphFavorite | parseFavoriteMutation |
GET/api/modules/record-graph/{recordId:guid}/knowledge | getRelatedKnowledge | parseRelatedKnowledge |
GET/api/modules/record-graph/{recordId:guid}/knowledge/candidates | getContextualKnowledge | parseContextualKnowledge |
PUT/api/modules/record-graph/{recordId:guid}/knowledge | linkKnowledgeToRecord | parseKnowledgeRelationMutation |
DELETE/api/modules/record-graph/knowledge-relations/{recordRelationId:guid} | unlinkKnowledgeFromRecord | parseKnowledgeRelationMutation |
Record activity 3 headless operations
Integration: page-module · Native key: module.record-activity
API roots: /api/modules/record-activity
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/record-activity/records | searchRecordActivity | parseRecordActivitySearch |
GET/api/modules/record-activity/{recordId:guid} | getRecordActivity | parseRecordActivity |
PUT/api/modules/record-activity/{recordId:guid}/favorite | setRecordActivityFavorite | parseFavoriteMutation |
Global secured search 2 headless operations
Integration: page-module · Native key: module.global-search
API roots: /api/modules/global-search
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/global-search | searchGlobalRecords | parseGlobalSearch |
PUT/api/modules/global-search/records/{recordId:guid}/favorite | setGlobalSearchFavorite | parseFavoriteMutation |
Ai Insights API 3 headless operations
Integration: api-surface · Native key: module.ai-insights
API roots: /api/modules/ai-insights
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/ai-insights | listAiInsights | parseAiInsightList |
GET/api/modules/ai-insights/{insightId:guid} | getAiInsight | parseAiInsightDetail |
PUT/api/modules/ai-insights/{insightId:guid}/state | setAiInsightState | parseAiInsightState |
Payments Module API 7 headless operations
Integration: api-surface · Native key: Not a page block
API roots: /api/modules/payments
| Exact HTTP route | Current browser function | Response parser |
|---|---|---|
GET/api/modules/payments/settings | getTenantPaymentSettings | parseTenantPaymentSettings |
PUT/api/modules/payments/settings/{moduleKey} | updateTenantPaymentPolicy | parseTenantPaymentMutation |
PUT/api/modules/payments/connectors | upsertTenantPaymentConnector | parseTenantPaymentMutation |
DELETE/api/modules/payments/connectors/{connectorId:guid} | deactivateTenantPaymentConnector | parseTenantPaymentMutation |
GET/api/modules/payments/methods | Use the typed transport/client | Use the returned typed contract |
GET/api/modules/payments/records/{recordId:guid} | getTenantRecordPayments | parseTenantRecordPaymentSummary |
POST/api/modules/payments/records/{recordId:guid}/charges | createTenantRecordCharge | parseTenantPaymentMutation |
Copy the searchable styled/unstyled operation directory
import { useMemo, useState } from "react";
import { headlessCapabilityRecipes } from "./HeadlessCapabilityRecipes.generated";
export const HeadlessOperationDirectory = ({ styled = false }: { readonly styled?: boolean }) => {
const [query, setQuery] = useState("");
const recipes = useMemo(() => {
const needle = query.trim().toLowerCase();
return needle ? headlessCapabilityRecipes.filter((recipe) => [recipe.title, recipe.slug, ...recipe.apiBasePaths, ...recipe.operations.flatMap((operation) => [operation.method, operation.route, ...operation.browserFunctions])].some((value) => value.toLowerCase().includes(needle))) : headlessCapabilityRecipes;
}, [query]);
return <section className={styled ? "bwhq-headless-directory" : undefined}>
<header><h1>Headless capability operations</h1><label>Search capability, route, or function<input type="search" value={query} onChange={(event) => setQuery(event.target.value)} /></label></header>
{recipes.map((recipe) => <details key={recipe.slug}><summary><strong>{recipe.title}</strong> <span>{recipe.operations.length} operations</span></summary><p>{recipe.integrationKind} · {recipe.nativeComponentKey || "No native page block"}</p>{recipe.operations.length === 0 ? <p>{recipe.integrationNote}</p> : <table><thead><tr><th>HTTP</th><th>Browser function</th><th>Parser</th></tr></thead><tbody>{recipe.operations.map((operation) => <tr key={`${operation.method} ${operation.route}`}><td><strong>{operation.method}</strong><br /><code>{operation.route}</code></td><td>{operation.browserFunctions.join(", ") || "Use typed transport/client"}</td><td>{operation.parsers.join(", ") || "See typed client contract"}</td></tr>)}</tbody></table>}</details>)}
</section>;
};
export const UnstyledHeadlessOperationDirectory = () => <HeadlessOperationDirectory />;
export const StyledHeadlessOperationDirectory = () => <HeadlessOperationDirectory styled />;Copy the complete machine-readable headless recipes
export interface HeadlessOperationRecipe {
readonly method: string;
readonly route: string;
readonly browserFunctions: readonly string[];
readonly parsers: readonly string[];
readonly procedures: readonly string[];
}
export interface HeadlessCapabilityRecipe {
readonly slug: string;
readonly title: string;
readonly integrationKind: "page-module" | "shell-component" | "background-service" | "api-surface";
readonly nativeComponentKey: string | null;
readonly apiBasePaths: readonly string[];
readonly clientMethods: readonly string[];
readonly operations: readonly HeadlessOperationRecipe[];
readonly integrationNote: string;
}
export const headlessCapabilityRecipes = [
{
"slug": "universal-inbox",
"title": "Universal Inbox",
"integrationKind": "shell-component",
"nativeComponentKey": null,
"apiBasePaths": [
"/api/inbox",
"/api/inbox/items"
],
"clientMethods": [
"list",
"get",
"badge",
"notifications",
"deliveryDebug",
"retryDelivery",
"setReadState",
"setStatus",
"setPriority",
"setAssignment",
"getEmailTicketingSettings",
"setEmailTicketing",
"decideWorkflowApproval"
],
"operations": [
{
"method": "GET",
"route": "/api/inbox/items",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_Inbox_GetQueueSecured"
]
},
{
"method": "GET",
"route": "/api/inbox/email-channels/ticketing",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_Inbox_GetEmailTicketingSettingsSecured"
]
},
{
"method": "PUT",
"route": "/api/inbox/email-channels/{channelConnectionId:guid}/ticketing",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_Inbox_SetEmailTicketingSecured"
]
},
{
"method": "GET",
"route": "/api/inbox/items/{inboxItemId:guid}",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_Inbox_GetItemDetailSecured"
]
},
{
"method": "GET",
"route": "/api/inbox/badge",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_GetInboxBadgeSecured"
]
},
{
"method": "GET",
"route": "/api/inbox/notifications",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_GetInboxNotificationsSecured"
]
},
{
"method": "GET",
"route": "/api/inbox/delivery/debug",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_GetDeliveryDebugSecured"
]
},
{
"method": "POST",
"route": "/api/inbox/delivery/{outboundMessageId:guid}/retry",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_RetryOutboundMessage"
]
},
{
"method": "PUT",
"route": "/api/inbox/items/{inboxItemId:guid}/human-state",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_Inbox_MarkRead"
]
},
{
"method": "POST",
"route": "/api/inbox/items/{inboxItemId:guid}/workflow-approval",
"browserFunctions": [],
"parsers": [],
"procedures": []
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "checklists-signoffs",
"title": "Checklists & Signoffs",
"integrationKind": "page-module",
"nativeComponentKey": "module.checklists-signoffs",
"apiBasePaths": [
"/api/modules/checklists-signoffs"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/checklists-signoffs/templates",
"browserFunctions": [
"listChecklistTemplates"
],
"parsers": [
"parseChecklistTemplateList"
],
"procedures": [
"sp_Checklists_ListTemplatesSecured"
]
},
{
"method": "POST",
"route": "/api/modules/checklists-signoffs/templates",
"browserFunctions": [
"createChecklistTemplate"
],
"parsers": [
"parseChecklistMutation"
],
"procedures": [
"sp_Checklists_CreateTemplateSecured"
]
},
{
"method": "GET",
"route": "/api/modules/checklists-signoffs/runs",
"browserFunctions": [
"listChecklistRuns"
],
"parsers": [
"parseChecklistRunList"
],
"procedures": [
"sp_Checklists_ListRunsSecured"
]
},
{
"method": "GET",
"route": "/api/modules/checklists-signoffs/runs/{checklistRunId:guid}",
"browserFunctions": [
"getChecklistRun"
],
"parsers": [
"parseChecklistRunDetail"
],
"procedures": [
"sp_Checklists_GetRunSecured"
]
},
{
"method": "POST",
"route": "/api/modules/checklists-signoffs/runs",
"browserFunctions": [
"startChecklistRun"
],
"parsers": [
"parseChecklistMutation"
],
"procedures": [
"sp_Checklists_StartRunSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/checklists-signoffs/items/{checklistRunItemId:guid}",
"browserFunctions": [
"updateChecklistItem"
],
"parsers": [
"parseChecklistMutation"
],
"procedures": [
"sp_Checklists_UpdateItemSecured"
]
},
{
"method": "POST",
"route": "/api/modules/checklists-signoffs/items/{checklistRunItemId:guid}/proof",
"browserFunctions": [
"attachChecklistProof"
],
"parsers": [
"parseChecklistMutation"
],
"procedures": [
"sp_Checklists_AttachProofSecured"
]
},
{
"method": "DELETE",
"route": "/api/modules/checklists-signoffs/proof/{checklistItemEvidenceId:guid}",
"browserFunctions": [
"removeChecklistProof"
],
"parsers": [
"parseChecklistMutation"
],
"procedures": [
"sp_Checklists_RemoveProofSecured"
]
},
{
"method": "POST",
"route": "/api/modules/checklists-signoffs/runs/{checklistRunId:guid}/submit",
"browserFunctions": [
"submitChecklistForSignoff"
],
"parsers": [
"parseChecklistMutation"
],
"procedures": [
"sp_Checklists_SubmitForSignoffSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "goclaw",
"title": "GoClaw virtual assistant",
"integrationKind": "shell-component",
"nativeComponentKey": null,
"apiBasePaths": [
"/api/goclaw/agents",
"/api/goclaw/approvals"
],
"clientMethods": [
"list",
"approve",
"reject",
"takeOver",
"retry"
],
"operations": [
{
"method": "PUT",
"route": "/api/goclaw/agents/{goClawAgentId:guid}/authority",
"browserFunctions": [],
"parsers": [],
"procedures": []
},
{
"method": "GET",
"route": "/api/goclaw/approvals",
"browserFunctions": [],
"parsers": [],
"procedures": []
},
{
"method": "POST",
"route": "/api/goclaw/approvals/{suggestionBatchId:guid}/approve",
"browserFunctions": [],
"parsers": [],
"procedures": []
},
{
"method": "POST",
"route": "/api/goclaw/approvals/{suggestionBatchId:guid}/reject",
"browserFunctions": [],
"parsers": [],
"procedures": []
},
{
"method": "POST",
"route": "/api/goclaw/approvals/{suggestionBatchId:guid}/take-over",
"browserFunctions": [],
"parsers": [],
"procedures": []
},
{
"method": "POST",
"route": "/api/goclaw/approvals/{suggestionBatchId:guid}/retry",
"browserFunctions": [],
"parsers": [],
"procedures": []
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "ai-insights",
"title": "AI Insights",
"integrationKind": "background-service",
"nativeComponentKey": null,
"apiBasePaths": [],
"clientMethods": [],
"operations": [],
"integrationNote": "This is a scheduled/background capability. Use its governed service and secured feed contracts when exposed; do not invent a browser mutation endpoint."
},
{
"slug": "contacts",
"title": "Contacts",
"integrationKind": "page-module",
"nativeComponentKey": "module.contacts",
"apiBasePaths": [
"/api/modules/contacts"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/contacts",
"browserFunctions": [
"listContacts"
],
"parsers": [
"parseContactList"
],
"procedures": [
"sp_Contacts_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/contacts/{recordId:guid}",
"browserFunctions": [
"getContact"
],
"parsers": [
"parseContactDetail"
],
"procedures": [
"sp_Contacts_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/contacts",
"browserFunctions": [
"createContact"
],
"parsers": [
"parseContactMutation"
],
"procedures": [
"sp_Contacts_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/contacts/{recordId:guid}",
"browserFunctions": [
"updateContact"
],
"parsers": [
"parseContactMutation"
],
"procedures": [
"sp_Contacts_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/contacts/{recordId:guid}/favorite",
"browserFunctions": [
"setContactFavorite"
],
"parsers": [
"parseContactMutation"
],
"procedures": [
"sp_Contacts_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "work-orders",
"title": "Work Orders",
"integrationKind": "page-module",
"nativeComponentKey": "module.work-orders",
"apiBasePaths": [
"/api/modules/work-orders"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/work-orders",
"browserFunctions": [
"listWorkOrders"
],
"parsers": [
"parseWorkOrderList"
],
"procedures": [
"sp_WorkOrders_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/work-orders/{recordId:guid}",
"browserFunctions": [
"getWorkOrder"
],
"parsers": [
"parseWorkOrderDetail"
],
"procedures": [
"sp_WorkOrders_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/work-orders",
"browserFunctions": [
"createWorkOrder"
],
"parsers": [
"parseWorkOrderMutation"
],
"procedures": [
"sp_WorkOrders_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/work-orders/{recordId:guid}",
"browserFunctions": [
"updateWorkOrder"
],
"parsers": [
"parseWorkOrderMutation"
],
"procedures": [
"sp_WorkOrders_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/work-orders/{recordId:guid}/status",
"browserFunctions": [
"setWorkOrderStatus"
],
"parsers": [
"parseWorkOrderMutation"
],
"procedures": [
"sp_WorkOrders_SetStatusSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/work-orders/{recordId:guid}/assignment",
"browserFunctions": [
"assignWorkOrder"
],
"parsers": [
"parseWorkOrderMutation"
],
"procedures": [
"sp_WorkOrders_AssignSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "reservations",
"title": "Reservations",
"integrationKind": "page-module",
"nativeComponentKey": "module.reservations",
"apiBasePaths": [
"/api/modules/reservations"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/reservations/products",
"browserFunctions": [
"listReservationProducts"
],
"parsers": [
"parseReservationProductList"
],
"procedures": [
"sp_ReservationProducts_ListSecured"
]
},
{
"method": "POST",
"route": "/api/modules/reservations/products",
"browserFunctions": [
"saveReservationProduct"
],
"parsers": [
"parseReservationMutation"
],
"procedures": [
"sp_ReservationProducts_UpsertSecured"
]
},
{
"method": "GET",
"route": "/api/modules/reservations",
"browserFunctions": [
"listReservations"
],
"parsers": [
"parseReservationList"
],
"procedures": [
"sp_Reservations_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/reservations/{recordId:guid}",
"browserFunctions": [
"getReservation"
],
"parsers": [
"parseReservationDetail"
],
"procedures": [
"sp_Reservations_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/reservations/purchase",
"browserFunctions": [
"purchaseReservation"
],
"parsers": [
"parseReservationMutation"
],
"procedures": [
"sp_Reservations_PurchaseSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/reservations/{recordId:guid}/status",
"browserFunctions": [
"setReservationStatus"
],
"parsers": [
"parseReservationMutation"
],
"procedures": [
"sp_Reservations_SetStatusSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/reservations/{recordId:guid}/followups",
"browserFunctions": [
"updateReservationFollowup"
],
"parsers": [
"parseReservationMutation"
],
"procedures": [
"sp_ReservationFollowups_UpdateSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "calendar",
"title": "Calendar",
"integrationKind": "page-module",
"nativeComponentKey": "module.calendar",
"apiBasePaths": [
"/api/modules/calendar"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/calendar",
"browserFunctions": [
"listCalendarEvents"
],
"parsers": [
"parseCalendarEventList"
],
"procedures": [
"sp_Calendar_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/calendar/{recordId:guid}",
"browserFunctions": [
"getCalendarEvent"
],
"parsers": [
"parseCalendarEventDetail"
],
"procedures": [
"sp_Calendar_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/calendar",
"browserFunctions": [
"createCalendarEvent"
],
"parsers": [
"parseCalendarMutation"
],
"procedures": [
"sp_Calendar_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/calendar/{recordId:guid}",
"browserFunctions": [
"updateCalendarEvent"
],
"parsers": [
"parseCalendarMutation"
],
"procedures": [
"sp_Calendar_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/calendar/{recordId:guid}/favorite",
"browserFunctions": [
"setCalendarFavorite"
],
"parsers": [
"parseCalendarMutation"
],
"procedures": [
"sp_Calendar_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "files",
"title": "Files & attachments",
"integrationKind": "page-module",
"nativeComponentKey": "module.files",
"apiBasePaths": [
"/api/modules/files"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/files",
"browserFunctions": [
"listFiles"
],
"parsers": [
"parseFileList"
],
"procedures": [
"sp_Files_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/files/{recordId:guid}",
"browserFunctions": [
"getFile"
],
"parsers": [
"parseFileDetail"
],
"procedures": [
"sp_Files_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/files/upload",
"browserFunctions": [
"uploadFile"
],
"parsers": [
"parseFileMutation"
],
"procedures": [
"sp_Files_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/files/{recordId:guid}",
"browserFunctions": [
"updateFile"
],
"parsers": [
"parseFileMutation"
],
"procedures": [
"sp_Files_UpdateSecured"
]
},
{
"method": "POST",
"route": "/api/modules/files/{recordId:guid}/attachments",
"browserFunctions": [
"attachFile"
],
"parsers": [
"parseFileMutation"
],
"procedures": [
"sp_Files_AttachSecured"
]
},
{
"method": "DELETE",
"route": "/api/modules/files/{recordId:guid}/attachments/{attachmentId:guid}",
"browserFunctions": [
"detachFile"
],
"parsers": [
"parseFileMutation"
],
"procedures": [
"sp_Files_DetachSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/files/{recordId:guid}/favorite",
"browserFunctions": [
"setFileFavorite"
],
"parsers": [
"parseFileMutation"
],
"procedures": [
"sp_Files_SetFavoriteSecured"
]
},
{
"method": "GET",
"route": "/api/modules/files/{recordId:guid}/content",
"browserFunctions": [
"downloadFileContent"
],
"parsers": [],
"procedures": [
"sp_Files_ListSecured",
"sp_Files_GetSecured",
"sp_Files_CreateSecured",
"sp_Files_UpdateSecured",
"sp_Files_AttachSecured",
"sp_Files_DetachSecured",
"sp_Files_SetFavoriteSecured",
"sp_Files_GetDownloadSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "conversations",
"title": "Conversations & messages",
"integrationKind": "page-module",
"nativeComponentKey": "module.conversations",
"apiBasePaths": [
"/api/modules/conversations"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/conversations",
"browserFunctions": [
"listConversations"
],
"parsers": [
"parseConversationList"
],
"procedures": [
"sp_Conversations_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/conversations/{recordId:guid}",
"browserFunctions": [
"getConversation"
],
"parsers": [
"parseConversationDetail"
],
"procedures": [
"sp_Conversations_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/conversations",
"browserFunctions": [
"createConversation"
],
"parsers": [
"parseConversationMutation"
],
"procedures": [
"sp_Conversations_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/conversations/{recordId:guid}",
"browserFunctions": [
"updateConversation"
],
"parsers": [
"parseConversationMutation"
],
"procedures": [
"sp_Conversations_UpdateSecured"
]
},
{
"method": "POST",
"route": "/api/modules/conversations/{recordId:guid}/messages",
"browserFunctions": [
"postConversationMessage"
],
"parsers": [
"parseConversationMutation"
],
"procedures": [
"sp_Conversations_ReplySecured"
]
},
{
"method": "POST",
"route": "/api/modules/conversations/direct",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_Conversations_SendDirectSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/conversations/{recordId:guid}/favorite",
"browserFunctions": [
"setConversationFavorite"
],
"parsers": [
"parseConversationMutation"
],
"procedures": [
"sp_Conversations_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "company-news",
"title": "Company news",
"integrationKind": "page-module",
"nativeComponentKey": "module.company-news",
"apiBasePaths": [
"/api/modules/company-news"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/company-news",
"browserFunctions": [
"listCompanyNews"
],
"parsers": [
"parseCompanyNewsList"
],
"procedures": [
"sp_CompanyNews_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/company-news/{recordId:guid}",
"browserFunctions": [
"getCompanyNews"
],
"parsers": [
"parseCompanyNewsDetail"
],
"procedures": [
"sp_CompanyNews_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/company-news",
"browserFunctions": [
"createCompanyNews"
],
"parsers": [
"parseCompanyNewsMutation"
],
"procedures": [
"sp_CompanyNews_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/company-news/{recordId:guid}",
"browserFunctions": [
"updateCompanyNews"
],
"parsers": [
"parseCompanyNewsMutation"
],
"procedures": [
"sp_CompanyNews_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/company-news/{recordId:guid}/favorite",
"browserFunctions": [
"setCompanyNewsFavorite"
],
"parsers": [
"parseCompanyNewsMutation"
],
"procedures": [
"sp_CompanyNews_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "knowledge-core",
"title": "Knowledge Core",
"integrationKind": "page-module",
"nativeComponentKey": "module.knowledge-articles",
"apiBasePaths": [
"/api/modules/knowledge-articles",
"/api/modules/knowledge-core"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/knowledge-articles",
"browserFunctions": [
"listKnowledgeArticles"
],
"parsers": [
"parseKnowledgeArticlesList"
],
"procedures": [
"sp_KnowledgeArticles_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-articles/{recordId:guid}",
"browserFunctions": [
"getKnowledgeArticle"
],
"parsers": [
"parseKnowledgeArticleDetail"
],
"procedures": [
"sp_KnowledgeArticles_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-articles",
"browserFunctions": [
"createKnowledgeArticle"
],
"parsers": [
"parseKnowledgeArticleMutation"
],
"procedures": [
"sp_KnowledgeArticles_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/knowledge-articles/{recordId:guid}",
"browserFunctions": [
"updateKnowledgeArticle"
],
"parsers": [
"parseKnowledgeArticleMutation"
],
"procedures": [
"sp_KnowledgeArticles_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/knowledge-articles/{recordId:guid}/favorite",
"browserFunctions": [
"setKnowledgeArticleFavorite"
],
"parsers": [
"parseKnowledgeArticleMutation"
],
"procedures": [
"sp_KnowledgeArticles_SetFavoriteSecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core",
"browserFunctions": [
"listKnowledgeCore"
],
"parsers": [
"parseKnowledgeCoreList"
],
"procedures": [
"sp_kc_ListKnowledgeItemsSecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/{recordId:guid}",
"browserFunctions": [
"getKnowledgeCore"
],
"parsers": [
"parseKnowledgeCoreDetail"
],
"procedures": [
"sp_kc_GetKnowledgeItemSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core",
"browserFunctions": [
"createKnowledgeCore"
],
"parsers": [
"parseKnowledgeCoreMutation"
],
"procedures": [
"sp_kc_CreateKnowledgeItem"
]
},
{
"method": "PUT",
"route": "/api/modules/knowledge-core/{recordId:guid}",
"browserFunctions": [
"updateKnowledgeCore"
],
"parsers": [
"parseKnowledgeCoreMutation"
],
"procedures": [
"sp_kc_UpdateKnowledgeItem"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/{recordId:guid}/publish",
"browserFunctions": [
"publishKnowledgeCore"
],
"parsers": [
"parseKnowledgeCoreMutation"
],
"procedures": [
"sp_kc_PublishKnowledgeItem"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/{recordId:guid}/archive",
"browserFunctions": [
"archiveKnowledgeCore"
],
"parsers": [
"parseKnowledgeCoreMutation"
],
"procedures": [
"sp_kc_ArchiveKnowledgeItem"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/{recordId:guid}/revisions",
"browserFunctions": [
"getKnowledgeCoreRevisions"
],
"parsers": [
"parseKnowledgeRevisions"
],
"procedures": [
"sp_kc_GetRevisionHistorySecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/{recordId:guid}/restore",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_RestoreRevisionAsDraft"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/collections",
"browserFunctions": [
"listKnowledgeCoreCollections"
],
"parsers": [
"parseKnowledgeCollections"
],
"procedures": [
"sp_kc_ListCollectionsSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/collections",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_CreateCollection"
]
},
{
"method": "PUT",
"route": "/api/modules/knowledge-core/collections/{collectionId:guid}",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_UpdateCollection"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/collections/{collectionId:guid}/items/{recordId:guid}",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_AddKnowledgeItemToCollection"
]
},
{
"method": "DELETE",
"route": "/api/modules/knowledge-core/collections/{collectionId:guid}/items/{recordId:guid}",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_RemoveKnowledgeItemFromCollection"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/{recordId:guid}/owners",
"browserFunctions": [
"getKnowledgeCoreOwners"
],
"parsers": [
"parseKnowledgeOwners"
],
"procedures": [
"sp_kc_GetKnowledgeOwnersSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/{recordId:guid}/owners",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_SetKnowledgeOwner"
]
},
{
"method": "DELETE",
"route": "/api/modules/knowledge-core/owners/{knowledgeOwnerId:guid}",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_RemoveKnowledgeOwner"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/unowned",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_GetUnownedKnowledgeSecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/reviews",
"browserFunctions": [
"listKnowledgeReviews"
],
"parsers": [
"parseKnowledgeReviews"
],
"procedures": [
"sp_kc_ListDueReviewsSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/reviews/{reviewCycleId:guid}/begin",
"browserFunctions": [
"beginKnowledgeReview"
],
"parsers": [
"parseKnowledgeReviewMutation"
],
"procedures": [
"sp_kc_BeginReview"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/reviews/{reviewCycleId:guid}/complete",
"browserFunctions": [
"completeKnowledgeReview"
],
"parsers": [
"parseKnowledgeReviewMutation"
],
"procedures": [
"sp_kc_CompleteReview"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/reviews/{reviewCycleId:guid}/reassign",
"browserFunctions": [
"reassignKnowledgeReview"
],
"parsers": [
"parseKnowledgeReviewMutation"
],
"procedures": [
"sp_kc_ReassignReview"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/health",
"browserFunctions": [
"getKnowledgeHealth"
],
"parsers": [
"parseKnowledgeHealth"
],
"procedures": [
"sp_kc_GetKnowledgeHealthSecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/questions",
"browserFunctions": [
"listKnowledgeQuestions"
],
"parsers": [
"parseKnowledgeQuestions"
],
"procedures": [
"sp_kc_GetOpenQuestionsSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/questions",
"browserFunctions": [
"createKnowledgeQuestion"
],
"parsers": [
"parseKnowledgeQuestionMutation"
],
"procedures": [
"sp_kc_CreateQuestion"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/questions/{knowledgeQuestionId:guid}/assign",
"browserFunctions": [
"assignKnowledgeQuestion"
],
"parsers": [
"parseKnowledgeQuestionMutation"
],
"procedures": [
"sp_kc_AssignQuestion"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/questions/{knowledgeQuestionId:guid}/answer",
"browserFunctions": [
"answerKnowledgeQuestion"
],
"parsers": [
"parseKnowledgeQuestionMutation"
],
"procedures": [
"sp_kc_AnswerQuestion"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/questions/{knowledgeQuestionId:guid}/convert",
"browserFunctions": [
"convertKnowledgeQuestion"
],
"parsers": [
"parseKnowledgeQuestionMutation"
],
"procedures": [
"sp_kc_ConvertQuestionToKnowledge"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/{recordId:guid}/feedback",
"browserFunctions": [
"recordKnowledgeFeedback"
],
"parsers": [
"parseKnowledgeFeedbackMutation"
],
"procedures": [
"sp_kc_RecordFeedback"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/{recordId:guid}/feedback",
"browserFunctions": [
"getKnowledgeFeedback"
],
"parsers": [
"parseKnowledgeFeedbackSummary"
],
"procedures": [
"sp_kc_GetKnowledgeFeedbackSummarySecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/gaps",
"browserFunctions": [
"getKnowledgeGaps"
],
"parsers": [
"parseKnowledgeGaps"
],
"procedures": [
"sp_kc_GetKnowledgeGapsSecured"
]
},
{
"method": "GET",
"route": "/api/modules/knowledge-core/support-learning/candidates",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_GetSupportLearningCandidatesSecured"
]
},
{
"method": "POST",
"route": "/api/modules/knowledge-core/support-learning/candidates",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_kc_CreateSupportResolutionCandidate"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "web-links",
"title": "Web links",
"integrationKind": "page-module",
"nativeComponentKey": "module.web-links",
"apiBasePaths": [
"/api/modules/web-links"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/web-links",
"browserFunctions": [
"listWebLinks"
],
"parsers": [
"parseWebLinksList"
],
"procedures": [
"sp_WebLinks_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/web-links/{recordId:guid}",
"browserFunctions": [
"getWebLink"
],
"parsers": [
"parseWebLinkDetail"
],
"procedures": [
"sp_WebLinks_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/web-links",
"browserFunctions": [
"createWebLink"
],
"parsers": [
"parseWebLinkMutation"
],
"procedures": [
"sp_WebLinks_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/web-links/{recordId:guid}",
"browserFunctions": [
"updateWebLink"
],
"parsers": [
"parseWebLinkMutation"
],
"procedures": [
"sp_WebLinks_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/web-links/{recordId:guid}/favorite",
"browserFunctions": [
"setWebLinkFavorite"
],
"parsers": [
"parseWebLinkMutation"
],
"procedures": [
"sp_WebLinks_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "chat-rooms",
"title": "Chat rooms",
"integrationKind": "page-module",
"nativeComponentKey": "module.chat-rooms",
"apiBasePaths": [
"/api/modules/chat-rooms"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/chat-rooms",
"browserFunctions": [
"listChatRooms"
],
"parsers": [
"parseChatRoomsList"
],
"procedures": [
"sp_ChatRooms_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/chat-rooms/{recordId:guid}",
"browserFunctions": [
"getChatRoom"
],
"parsers": [
"parseChatRoomDetail"
],
"procedures": [
"sp_ChatRooms_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/chat-rooms",
"browserFunctions": [
"createChatRoom"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/chat-rooms/{recordId:guid}",
"browserFunctions": [
"updateChatRoom"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_UpdateSecured"
]
},
{
"method": "POST",
"route": "/api/modules/chat-rooms/{recordId:guid}/messages",
"browserFunctions": [
"postChatMessage"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_PostMessageSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/chat-rooms/{recordId:guid}/messages/{chatMessageId:guid}/reaction",
"browserFunctions": [
"setChatReaction"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_SetReactionSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/chat-rooms/{recordId:guid}/members/{memberUserId:guid}",
"browserFunctions": [
"setChatRoomMember"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_SetMemberSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/chat-rooms/{recordId:guid}/read",
"browserFunctions": [
"markChatRoomRead"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_MarkReadSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/chat-rooms/{recordId:guid}/favorite",
"browserFunctions": [
"setChatRoomFavorite"
],
"parsers": [
"parseChatRoomMutation"
],
"procedures": [
"sp_ChatRooms_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "discussion-boards",
"title": "Discussion boards",
"integrationKind": "page-module",
"nativeComponentKey": "module.discussion-boards",
"apiBasePaths": [
"/api/modules/discussion-boards"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/discussion-boards",
"browserFunctions": [
"listDiscussionBoards"
],
"parsers": [
"parseDiscussionBoardsList"
],
"procedures": [
"sp_DiscussionBoards_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/discussion-boards/{recordId:guid}",
"browserFunctions": [
"getDiscussionBoard"
],
"parsers": [
"parseDiscussionBoardDetail"
],
"procedures": [
"sp_DiscussionBoards_GetBoardSecured"
]
},
{
"method": "POST",
"route": "/api/modules/discussion-boards",
"browserFunctions": [
"createDiscussionBoard"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_CreateBoardSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/discussion-boards/{recordId:guid}",
"browserFunctions": [
"updateDiscussionBoard"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_UpdateBoardSecured"
]
},
{
"method": "POST",
"route": "/api/modules/discussion-boards/{boardRecordId:guid}/topics",
"browserFunctions": [
"createDiscussionTopic"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_CreateTopicSecured"
]
},
{
"method": "GET",
"route": "/api/modules/discussion-boards/topics/{recordId:guid}",
"browserFunctions": [
"getDiscussionTopic"
],
"parsers": [
"parseDiscussionTopicDetail"
],
"procedures": [
"sp_DiscussionBoards_GetTopicSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/discussion-boards/topics/{recordId:guid}",
"browserFunctions": [
"updateDiscussionTopic"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_UpdateTopicSecured"
]
},
{
"method": "POST",
"route": "/api/modules/discussion-boards/topics/{topicRecordId:guid}/posts",
"browserFunctions": [
"postDiscussionReply"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_PostReplySecured"
]
},
{
"method": "PUT",
"route": "/api/modules/discussion-boards/posts/{recordId:guid}",
"browserFunctions": [
"updateDiscussionPost"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_UpdatePostSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/discussion-boards/records/{recordId:guid}/favorite",
"browserFunctions": [
"setDiscussionFavorite"
],
"parsers": [
"parseDiscussionMutation"
],
"procedures": [
"sp_DiscussionBoards_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "mail-reader",
"title": "Mail reader",
"integrationKind": "page-module",
"nativeComponentKey": "module.mail-reader",
"apiBasePaths": [
"/api/modules/mail-reader"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/mail-reader",
"browserFunctions": [
"listMailReaderMessages"
],
"parsers": [
"parseMailReaderList"
],
"procedures": [
"sp_MailReader_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/mail-reader/{recordId:guid}",
"browserFunctions": [
"getMailReaderMessage"
],
"parsers": [
"parseMailReaderDetail"
],
"procedures": [
"sp_MailReader_GetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/mail-reader/{recordId:guid}/read",
"browserFunctions": [
"setMailReaderRead"
],
"parsers": [
"parseMailReaderMutation"
],
"procedures": [
"sp_MailReader_SetReadSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/mail-reader/{recordId:guid}/favorite",
"browserFunctions": [
"setMailReaderFavorite"
],
"parsers": [
"parseMailReaderMutation"
],
"procedures": [
"sp_MailReader_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "favorites",
"title": "Favorites",
"integrationKind": "page-module",
"nativeComponentKey": "module.favorites",
"apiBasePaths": [
"/api/modules/favorites"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/favorites",
"browserFunctions": [
"listFavorites"
],
"parsers": [
"parseFavoritesList"
],
"procedures": [
"sp_Favorites_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/favorites/{recordId:guid}",
"browserFunctions": [
"getFavorite"
],
"parsers": [
"parseFavoriteDetail"
],
"procedures": [
"sp_Favorites_GetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/favorites/{recordId:guid}/favorite",
"browserFunctions": [
"setFavorite"
],
"parsers": [
"parseFavoriteMutation"
],
"procedures": [
"sp_Favorites_SetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/favorites/{recordId:guid}/preferences",
"browserFunctions": [
"updateFavoritePreferences"
],
"parsers": [
"parseFavoriteMutation"
],
"procedures": [
"sp_Favorites_UpdateSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "notifications",
"title": "Notifications",
"integrationKind": "page-module",
"nativeComponentKey": "module.notifications",
"apiBasePaths": [
"/api/modules/notifications"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/notifications",
"browserFunctions": [
"listNotifications"
],
"parsers": [
"parseNotificationList"
],
"procedures": [
"sp_Notifications_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/notifications/{notificationId:guid}",
"browserFunctions": [
"getNotification"
],
"parsers": [
"parseNotificationDetail"
],
"procedures": [
"sp_Notifications_GetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/notifications/{notificationId:guid}/state",
"browserFunctions": [
"setNotificationState"
],
"parsers": [
"parseNotificationMutation"
],
"procedures": [
"sp_Notifications_SetStateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/notifications/{notificationId:guid}/source-favorite",
"browserFunctions": [
"setNotificationSourceFavorite"
],
"parsers": [
"parseNotificationMutation"
],
"procedures": [
"sp_Notifications_SetSourceFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "dynamic-records",
"title": "Dynamic/custom records",
"integrationKind": "page-module",
"nativeComponentKey": "module.dynamic-records",
"apiBasePaths": [
"/api/modules/dynamic"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/dynamic/{moduleKey}/schema",
"browserFunctions": [
"getDynamicModuleSchema"
],
"parsers": [
"parseDynamicModuleSchema"
],
"procedures": [
"sp_DynamicModules_GetSchemaSecured"
]
},
{
"method": "GET",
"route": "/api/modules/dynamic/{moduleKey}",
"browserFunctions": [
"listDynamicModuleRecords"
],
"parsers": [
"parseDynamicModuleList"
],
"procedures": [
"sp_DynamicModules_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/dynamic/{moduleKey}/{recordId:guid}",
"browserFunctions": [
"getDynamicModuleRecord"
],
"parsers": [
"parseDynamicModuleDetail"
],
"procedures": [
"sp_DynamicModules_GetSecured"
]
},
{
"method": "POST",
"route": "/api/modules/dynamic/{moduleKey}",
"browserFunctions": [
"createDynamicModuleRecord"
],
"parsers": [
"parseDynamicModuleMutation"
],
"procedures": [
"sp_DynamicModules_CreateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/dynamic/{moduleKey}/{recordId:guid}",
"browserFunctions": [
"updateDynamicModuleRecord"
],
"parsers": [
"parseDynamicModuleMutation"
],
"procedures": [
"sp_DynamicModules_UpdateSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/dynamic/{moduleKey}/{recordId:guid}/favorite",
"browserFunctions": [
"setDynamicModuleFavorite"
],
"parsers": [
"parseDynamicModuleMutation"
],
"procedures": [
"sp_DynamicModules_SetFavoriteSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "active-workplace",
"title": "ActiveWorkplace",
"integrationKind": "page-module",
"nativeComponentKey": "module.active-workplace",
"apiBasePaths": [
"/api/modules/active-workplace"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/active-workplace",
"browserFunctions": [
"listActiveWorkplaces"
],
"parsers": [
"parseActiveWorkplaceList"
],
"procedures": [
"sp_ActiveWorkplace_ListSecured"
]
},
{
"method": "POST",
"route": "/api/modules/active-workplace",
"browserFunctions": [
"createActiveWorkplace"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_CreateSecured"
]
},
{
"method": "GET",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}",
"browserFunctions": [
"getActiveWorkplace"
],
"parsers": [
"parseActiveWorkplaceDetail"
],
"procedures": [
"sp_ActiveWorkplace_GetSecured"
]
},
{
"method": "PATCH",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}",
"browserFunctions": [
"updateActiveWorkplace"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_UpdateSecured"
]
},
{
"method": "POST",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/status",
"browserFunctions": [
"setActiveWorkplaceStatus"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_SetStatusSecured"
]
},
{
"method": "GET",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/participants/catalog",
"browserFunctions": [
"getActiveWorkplaceParticipantCatalog"
],
"parsers": [
"parseActiveWorkplaceCatalog"
],
"procedures": [
"sp_ActiveWorkplace_GetParticipantCatalogSecured"
]
},
{
"method": "POST",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/participants",
"browserFunctions": [
"addActiveWorkplaceParticipant"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_AddParticipantSecured"
]
},
{
"method": "DELETE",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/participants/{activeWorkplaceParticipantId:guid}",
"browserFunctions": [
"removeActiveWorkplaceParticipant"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_RemoveParticipantSecured"
]
},
{
"method": "POST",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/activity",
"browserFunctions": [
"recordActiveWorkplaceActivity"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_RecordActivitySecured"
]
},
{
"method": "POST",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/graph/refresh",
"browserFunctions": [
"refreshActiveWorkplaceGraph"
],
"parsers": [
"parseActiveWorkplaceMutation"
],
"procedures": [
"sp_ActiveWorkplace_RefreshGraphSecured"
]
},
{
"method": "GET",
"route": "/api/modules/active-workplace/{activeWorkplaceId:guid}/playback",
"browserFunctions": [
"getActiveWorkplacePlayback"
],
"parsers": [
"parseActiveWorkplacePlayback"
],
"procedures": [
"sp_ActiveWorkplace_GetPlaybackSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "record-relations",
"title": "Record relations",
"integrationKind": "page-module",
"nativeComponentKey": "module.record-graph",
"apiBasePaths": [
"/api/modules/record-graph"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/record-graph/records",
"browserFunctions": [
"searchRecordGraph"
],
"parsers": [
"parseRecordGraphSearch"
],
"procedures": [
"sp_RecordGraph_SearchSecured"
]
},
{
"method": "GET",
"route": "/api/modules/record-graph/{recordId:guid}",
"browserFunctions": [
"getRecordGraph"
],
"parsers": [
"parseRecordGraph"
],
"procedures": [
"sp_RecordGraph_GetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/record-graph/{recordId:guid}/relations",
"browserFunctions": [
"addRecordGraphRelation"
],
"parsers": [
"parseRecordGraphMutation"
],
"procedures": [
"sp_RecordGraph_AddRelationSecured"
]
},
{
"method": "DELETE",
"route": "/api/modules/record-graph/relations/{recordRelationId:guid}",
"browserFunctions": [
"removeRecordGraphRelation"
],
"parsers": [
"parseRecordGraphMutation"
],
"procedures": [
"sp_RecordGraph_RemoveRelationSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/record-graph/{recordId:guid}/favorite",
"browserFunctions": [
"setRecordGraphFavorite"
],
"parsers": [
"parseFavoriteMutation"
],
"procedures": [
"sp_Favorites_SetSecured"
]
},
{
"method": "GET",
"route": "/api/modules/record-graph/{recordId:guid}/knowledge",
"browserFunctions": [
"getRelatedKnowledge"
],
"parsers": [
"parseRelatedKnowledge"
],
"procedures": [
"sp_kc_GetRelatedKnowledgeSecured"
]
},
{
"method": "GET",
"route": "/api/modules/record-graph/{recordId:guid}/knowledge/candidates",
"browserFunctions": [
"getContextualKnowledge"
],
"parsers": [
"parseContextualKnowledge"
],
"procedures": [
"sp_kc_GetContextualKnowledgeCandidatesSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/record-graph/{recordId:guid}/knowledge",
"browserFunctions": [
"linkKnowledgeToRecord"
],
"parsers": [
"parseKnowledgeRelationMutation"
],
"procedures": [
"sp_kc_LinkKnowledgeToRecord"
]
},
{
"method": "DELETE",
"route": "/api/modules/record-graph/knowledge-relations/{recordRelationId:guid}",
"browserFunctions": [
"unlinkKnowledgeFromRecord"
],
"parsers": [
"parseKnowledgeRelationMutation"
],
"procedures": [
"sp_kc_UnlinkKnowledgeFromRecord"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "record-activity",
"title": "Record activity",
"integrationKind": "page-module",
"nativeComponentKey": "module.record-activity",
"apiBasePaths": [
"/api/modules/record-activity"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/record-activity/records",
"browserFunctions": [
"searchRecordActivity"
],
"parsers": [
"parseRecordActivitySearch"
],
"procedures": [
"sp_RecordActivity_SearchSecured"
]
},
{
"method": "GET",
"route": "/api/modules/record-activity/{recordId:guid}",
"browserFunctions": [
"getRecordActivity"
],
"parsers": [
"parseRecordActivity"
],
"procedures": [
"sp_RecordActivity_GetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/record-activity/{recordId:guid}/favorite",
"browserFunctions": [
"setRecordActivityFavorite"
],
"parsers": [
"parseFavoriteMutation"
],
"procedures": [
"sp_Favorites_SetSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "global-search",
"title": "Global secured search",
"integrationKind": "page-module",
"nativeComponentKey": "module.global-search",
"apiBasePaths": [
"/api/modules/global-search"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/global-search",
"browserFunctions": [
"searchGlobalRecords"
],
"parsers": [
"parseGlobalSearch"
],
"procedures": [
"sp_GlobalSearch_SearchSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/global-search/records/{recordId:guid}/favorite",
"browserFunctions": [
"setGlobalSearchFavorite"
],
"parsers": [
"parseFavoriteMutation"
],
"procedures": [
"sp_Favorites_SetSecured"
]
}
],
"integrationNote": "Use the current typed client or the exact operations listed here."
},
{
"slug": "api-modules-ai-insights-api",
"title": "Ai Insights API",
"integrationKind": "api-surface",
"nativeComponentKey": "module.ai-insights",
"apiBasePaths": [
"/api/modules/ai-insights"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/ai-insights",
"browserFunctions": [
"listAiInsights"
],
"parsers": [
"parseAiInsightList"
],
"procedures": [
"sp_AiInsights_ListSecured"
]
},
{
"method": "GET",
"route": "/api/modules/ai-insights/{insightId:guid}",
"browserFunctions": [
"getAiInsight"
],
"parsers": [
"parseAiInsightDetail"
],
"procedures": [
"sp_AiInsights_GetSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/ai-insights/{insightId:guid}/state",
"browserFunctions": [
"setAiInsightState"
],
"parsers": [
"parseAiInsightState"
],
"procedures": [
"sp_AiInsights_SetStateSecured"
]
}
],
"integrationNote": "This API surface supports other first-class modules and has no standalone page renderer."
},
{
"slug": "api-modules-payments-api",
"title": "Payments Module API",
"integrationKind": "api-surface",
"nativeComponentKey": null,
"apiBasePaths": [
"/api/modules/payments"
],
"clientMethods": [],
"operations": [
{
"method": "GET",
"route": "/api/modules/payments/settings",
"browserFunctions": [
"getTenantPaymentSettings"
],
"parsers": [
"parseTenantPaymentSettings"
],
"procedures": [
"sp_TenantPayments_GetSettingsSecured"
]
},
{
"method": "PUT",
"route": "/api/modules/payments/settings/{moduleKey}",
"browserFunctions": [
"updateTenantPaymentPolicy"
],
"parsers": [
"parseTenantPaymentMutation"
],
"procedures": [
"sp_TenantPayments_UpdatePolicySecured"
]
},
{
"method": "PUT",
"route": "/api/modules/payments/connectors",
"browserFunctions": [
"upsertTenantPaymentConnector"
],
"parsers": [
"parseTenantPaymentMutation"
],
"procedures": [
"sp_TenantPayments_UpsertConnectorSecured"
]
},
{
"method": "DELETE",
"route": "/api/modules/payments/connectors/{connectorId:guid}",
"browserFunctions": [
"deactivateTenantPaymentConnector"
],
"parsers": [
"parseTenantPaymentMutation"
],
"procedures": [
"sp_TenantPayments_DeactivateConnectorSecured"
]
},
{
"method": "GET",
"route": "/api/modules/payments/methods",
"browserFunctions": [],
"parsers": [],
"procedures": [
"sp_TenantPayments_ListMethodsSecured"
]
},
{
"method": "GET",
"route": "/api/modules/payments/records/{recordId:guid}",
"browserFunctions": [
"getTenantRecordPayments"
],
"parsers": [
"parseTenantRecordPaymentSummary"
],
"procedures": [
"sp_TenantPayments_GetRecordSummarySecured"
]
},
{
"method": "POST",
"route": "/api/modules/payments/records/{recordId:guid}/charges",
"browserFunctions": [
"createTenantRecordCharge"
],
"parsers": [
"parseTenantPaymentMutation"
],
"procedures": [
"sp_TenantPayments_CreateChargeSecured"
]
}
],
"integrationNote": "This API surface supports other first-class modules and has no standalone page renderer."
}
] as const satisfies readonly HeadlessCapabilityRecipe[];9. Headless release checklist
- Run a real login, refresh, reload, logout and expired-session journey; do not mock the transport in the only end-to-end test.
- Probe every detail and mutation with an own ID, another tenant's real ID, and a random ID. Foreign/absent responses must not become an existence oracle.
- Verify DataRole, Location, secure-field, AI-read and action permission changes take effect on the next request.
- Assert list cardinality, stable ordering, first/middle/deep pagination, bounded payload size and no client-side “fetch everything then filter” path.
- Exercise create/update/stale update/duplicate request, file failure, Workflow approval, ticket resolution, Inbox activity changes, rate limiting and restart recovery.
- Keep correlation IDs through browser, API, SQL, workers and provider delivery; log safe codes, never tokens, secrets, SQL parameters or returned tenant data.
- Test keyboard/screen-reader behavior, mobile layout, large photos, slow connections, 401/403/404/409/429/5xx states and abort/navigation races.
Use the native React catalog when the platform component already matches the experience, and the Developer Platform for external/server-to-server applications.