Are you an LLM? You can read better optimized documentation at /apps/reference/messages.md for this page in Markdown format
Message bridge
A block and its host talk over window.postMessage. Every message is a { type, payload } object discriminated by type. The tables below are generated from the published @civitai/app-sdk message unions (for payload shapes) joined with the civitai host parity inventory (for direction, request/reply pairing, and page-only flags).
Most builders never send these by hand — the React hooks wrap them. This page is the contract for advanced use and non-React SDK consumers.
Conventions
- block → host vs host → block — the direction of the message.
- request → reply — a request-style message that awaits a specific reply type (shown). An unhandled request-style message hangs the block until its SDK timeout, so the host always registers a handler.
- fire-and-forget — a block → host message with no reply; ignoring it is a silent no-op, never a hang.
- page-only — handled only by the full-page host (a page app at
/apps/run/<slug>), not by the model-slot host today. Slot apps are deferred during the closed beta, so build page apps and you get the full surface.
Lifecycle
BLOCK_ERRORblock → hostfire-and-forgetpayload
{
message: string;
fatal: boolean;
}BLOCK_INIThost → blockpayload
BlockInitPayloadBLOCK_READYblock → hostfire-and-forgetpayload
{
height: number;
}NAVIGATEblock → hostfire-and-forgetpage-onlypayload
{
path: string;
target: 'current' | 'new_tab';
}Model slot: model slot is an embedded panel; host-navigation is out of remit (no NAVIGATE bridge)
RESIZE_IFRAMEblock → hostfire-and-forgetpayload
{
height: number;
}RESUMEhost → blockpayload
(no payload)SUSPENDhost → blockpayload
(no payload)TRACK_EVENTblock → hostfire-and-forgetpayload
{
eventName: string;
properties?: Record<string, unknown>;
}Auth & token
REQUEST_CONSENTblock → hostfire-and-forgetpayload
{
scopes?: string[];
}REQUEST_SIGN_INblock → hostfire-and-forgetpayload
{
returnUrl?: string;
}REQUEST_TOKENblock → hostrequest → replypayload
{
requestId: string;
blockInstanceId: string;
}reply
TOKEN_REFRESH_RESPONSE{
requestId?: string;
token: WrappedToken;
}TOKEN_REFRESHhost → blockpayload
{
token: WrappedToken;
}Generation workflows
CANCEL_WORKFLOWblock → hostrequest → replypayload
{
requestId: string;
workflowId: string;
}reply
WORKFLOW_CANCELED{
requestId: string;
snapshot: BlockWorkflowSnapshot;
}ESTIMATE_WORKFLOWblock → hostrequest → replypayload
{
requestId: string;
body: WorkflowBody;
}reply
ESTIMATE_RESULT{
requestId: string;
snapshot: BlockWorkflowSnapshot;
}POLL_WORKFLOWblock → hostrequest → replypayload
{
requestId: string;
workflowId: string;
}reply
WORKFLOW_STATUS{
requestId: string;
snapshot: BlockWorkflowSnapshot;
}SUBMIT_WORKFLOWblock → hostrequest → replypayload
{
requestId: string;
body: WorkflowBody;
}reply
WORKFLOW_SUBMITTED{
requestId: string;
snapshot: BlockWorkflowSnapshot;
}App subqueue
CANCEL_APP_WORKFLOWblock → hostrequest → replypage-onlypayload
{
requestId: string;
workflowId: string;
}reply
CANCEL_APP_WORKFLOW_RESULT{
requestId: string;
result?: {
workflow: AppWorkflow;
};
error?: string;
}Model slot: app subqueue is a page-only affordance today; slot-apps deferred
QUERY_APP_WORKFLOWSblock → hostrequest → replypage-onlypayload
{
requestId: string;
params?: AppWorkflowsParams;
}reply
APP_WORKFLOWS_RESULT{
requestId: string;
result?: {
workflows: AppWorkflow[];
cursor: string | null;
};
error?: string;
}Model slot: app subqueue is a page-only affordance today; slot-apps deferred
Buzz
GET_BUZZ_ACCOUNTSblock → hostrequest → replypage-onlypayload
{
requestId: string;
}reply
BUZZ_ACCOUNTS_RESULT{
requestId: string;
result?: {
accounts: BlockBuzzAccount[];
};
error?: string;
}Model slot: buzz self-read dashboard is a page-only affordance; slot-apps deferred
GET_BUZZ_BALANCEblock → hostrequest → replypayload
{
requestId: string;
}reply
BUZZ_BALANCE_RESULT{
requestId: string;
balance?: {
blue: number;
green: number;
yellow: number;
};
error?: string;
}GET_BUZZ_TRANSACTIONSblock → hostrequest → replypage-onlypayload
{
requestId: string;
params?: BlockBuzzTransactionsParams;
}reply
BUZZ_TRANSACTIONS_RESULT{
requestId: string;
result?: {
cursor?: string;
transactions: BlockBuzzTransaction[];
};
error?: string;
}Model slot: buzz self-read dashboard is a page-only affordance; slot-apps deferred
GET_DAILY_COMPENSATIONblock → hostrequest → replypage-onlypayload
{
requestId: string;
params?: BlockDailyCompensationParams;
}reply
DAILY_COMPENSATION_RESULT{
requestId: string;
result?: {
resources: BlockDailyCompensationResource[];
hasPublishedResources: boolean;
};
error?: string;
}Model slot: buzz self-read dashboard is a page-only affordance; slot-apps deferred
OPEN_BUZZ_PURCHASEblock → hostrequest → replypayload
{
requestId: string;
suggestedAmount?: number;
}reply
BUZZ_PURCHASE_RESULT{
requestId: string;
purchased: boolean;
newBalance?: number;
}Viewer
GET_VIEWERblock → hostrequest → replypage-onlypayload
{
requestId: string;
}reply
VIEWER_RESULT{
requestId: string;
viewer?: BlockViewer;
error?: string;
}Model slot: viewer self-read is a page-only affordance; slot-apps deferred
Pickers & upload
IMAGE_SCAN_RESOLVEDhost → blockpayload
{
requestId: string;
imageId: number;
result: BlockImageScanResult;
}OPEN_CHECKPOINT_PICKERblock → hostrequest → replypayload
{
requestId: string;
baseModelGroup: string;
/** Currently-selected versionId so the picker can pre-highlight it. */
currentVersionId?: number;
}reply
CHECKPOINT_PICKER_RESULT{
requestId: string;
selected?: BlockCheckpointInfo;
}OPEN_IMAGE_UPLOADblock → hostrequest → replypage-onlypayload
{
requestId: string;
purpose?: BlockUploadPurpose;
asyncScan?: boolean;
}reply
IMAGE_UPLOAD_RESULT{
requestId: string;
selected?: BlockUploadedImageInfo | BlockGenerationSourceImageInfo | BlockPendingImageInfo;
}Model slot: host-mediated image upload is a page-only affordance today; the model slot has no such surface
OPEN_RESOURCE_PICKERblock → hostrequest → replypage-onlypayload
{
requestId: string;
resourceType: BlockResourcePickerType;
/** Optional base-model family hint (ecosystem key or baseModel name). */
baseModelGroup?: string;
}reply
RESOURCE_PICKER_RESULT{
requestId: string;
selected?: BlockResourceInfo;
}Model slot: model slot uses the narrower OPEN_CHECKPOINT_PICKER; the wider resource picker is a page-only affordance
SET_USER_CHECKPOINTblock → hostrequest → replypayload
{
requestId: string;
versionId: number | null;
}reply
USER_CHECKPOINT_SET{
requestId: string;
ok: boolean;
error?: string;
}Per-app storage
APP_STORAGE_DELETEblock → hostrequest → replypayload
{
requestId: string;
key: string;
}reply
APP_STORAGE_DELETE_RESULT{
requestId: string;
ok: boolean;
deleted: boolean;
error?: string;
}APP_STORAGE_GETblock → hostrequest → replypayload
{
requestId: string;
key: string;
}reply
APP_STORAGE_GET_RESULT{
requestId: string;
value: unknown;
error?: string;
}APP_STORAGE_LISTblock → hostrequest → replypayload
{
requestId: string;
prefix?: string;
limit?: number;
cursor?: string;
}reply
APP_STORAGE_LIST_RESULT{
requestId: string;
keys: Array<{
key: string;
updatedAt: string;
}>;
nextCursor?: string;
error?: string;
}APP_STORAGE_QUOTAblock → hostrequest → replypayload
{
requestId: string;
}reply
APP_STORAGE_QUOTA_RESULT{
requestId: string;
usedBytes: number;
rowCount: number;
limitBytes: number;
limitRows: number;
error?: string;
}APP_STORAGE_SETblock → hostrequest → replypayload
{
requestId: string;
key: string;
value: unknown;
}reply
APP_STORAGE_SET_RESULT{
requestId: string;
ok: boolean;
error?: string;
sizeBytes?: number;
}Shared storage
SHARED_APPENDblock → hostrequest → replypayload
{
requestId: string;
value: SharedStorageValue;
}reply
SHARED_APPEND_RESULT{
requestId: string;
key: string;
error?: string;
}SHARED_GET_COUNTblock → hostrequest → replypayload
{
requestId: string;
key: string;
}reply
SHARED_GET_COUNT_RESULT{
requestId: string;
count: number;
error?: string;
}SHARED_GET_COUNTSblock → hostrequest → replypayload
{
requestId: string;
keys: string[];
}reply
SHARED_GET_COUNTS_RESULT{
requestId: string;
counts: Record<string, number>;
error?: string;
}SHARED_LISTblock → hostrequest → replypayload
{
requestId: string;
prefix?: string;
limit?: number;
cursor?: string;
}reply
SHARED_LIST_RESULT{
requestId: string;
items: SharedStorageItemWire[];
nextCursor?: string;
error?: string;
}SHARED_UNVOTEblock → hostrequest → replypayload
{
requestId: string;
key: string;
}reply
SHARED_UNVOTE_RESULT{
requestId: string;
count: number;
error?: string;
}SHARED_UPDATEblock → hostrequest → replypayload
{
requestId: string;
key: string;
value: SharedStorageValue;
}reply
SHARED_UPDATE_RESULT{
requestId: string;
ok: boolean;
error?: string;
}SHARED_VOTEblock → hostrequest → replypayload
{
requestId: string;
key: string;
}reply
SHARED_VOTE_RESULT{
requestId: string;
count: number;
error?: string;
}SHARED_WITHDRAWblock → hostrequest → replypayload
{
requestId: string;
key: string;
}reply
SHARED_WITHDRAW_RESULT{
requestId: string;
ok: boolean;
deleted: boolean;
error?: string;
}Wildcard packs
GET_WILDCARD_PACKblock → hostrequest → replypage-onlypayload
{
requestId: string;
modelVersionId: number;
}reply
WILDCARD_PACK_RESULT{
requestId: string;
pack?: BlockWildcardPack;
error?: BlockWildcardPackErrorCode;
}Model slot: model slot has no wildcard-pack import surface; the resolve+parse bridge is a page-only affordance
Payloads reference SDK types
Some payload fields are typed as named SDK interfaces (for example WorkflowBody, BlockViewer, AppWorkflow). Those come from @civitai/app-sdk/blocks — import the package to get the full type definitions in your editor.