Skip to content

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-forget
payload
{
    message: string;
    fatal: boolean;
}
BLOCK_INIThost → block
payload
BlockInitPayload
BLOCK_READYblock → hostfire-and-forget
payload
{
    height: number;
}
NAVIGATEblock → hostfire-and-forgetpage-only
payload
{
    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-forget
payload
{
    height: number;
}
RESUMEhost → block
payload
(no payload)
SUSPENDhost → block
payload
(no payload)
TRACK_EVENTblock → hostfire-and-forget
payload
{
    eventName: string;
    properties?: Record<string, unknown>;
}

Auth & token

REQUEST_CONSENTblock → hostfire-and-forget
payload
{
    scopes?: string[];
}
REQUEST_SIGN_INblock → hostfire-and-forget
payload
{
    returnUrl?: string;
}
REQUEST_TOKENblock → hostrequest → reply
payload
{
    requestId: string;
    blockInstanceId: string;
}
reply TOKEN_REFRESH_RESPONSE
{
    requestId?: string;
    token: WrappedToken;
}
TOKEN_REFRESHhost → block
payload
{
    token: WrappedToken;
}

Generation workflows

CANCEL_WORKFLOWblock → hostrequest → reply
payload
{
    requestId: string;
    workflowId: string;
}
reply WORKFLOW_CANCELED
{
    requestId: string;
    snapshot: BlockWorkflowSnapshot;
}
ESTIMATE_WORKFLOWblock → hostrequest → reply
payload
{
    requestId: string;
    body: WorkflowBody;
}
reply ESTIMATE_RESULT
{
    requestId: string;
    snapshot: BlockWorkflowSnapshot;
}
POLL_WORKFLOWblock → hostrequest → reply
payload
{
    requestId: string;
    workflowId: string;
}
reply WORKFLOW_STATUS
{
    requestId: string;
    snapshot: BlockWorkflowSnapshot;
}
SUBMIT_WORKFLOWblock → hostrequest → reply
payload
{
    requestId: string;
    body: WorkflowBody;
}
reply WORKFLOW_SUBMITTED
{
    requestId: string;
    snapshot: BlockWorkflowSnapshot;
}

App subqueue

CANCEL_APP_WORKFLOWblock → hostrequest → replypage-only
payload
{
    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-only
payload
{
    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-only
payload
{
    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 → reply
payload
{
    requestId: string;
}
reply BUZZ_BALANCE_RESULT
{
    requestId: string;
    balance?: {
        blue: number;
        green: number;
        yellow: number;
    };
    error?: string;
}
GET_BUZZ_TRANSACTIONSblock → hostrequest → replypage-only
payload
{
    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-only
payload
{
    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 → reply
payload
{
    requestId: string;
    suggestedAmount?: number;
}
reply BUZZ_PURCHASE_RESULT
{
    requestId: string;
    purchased: boolean;
    newBalance?: number;
}

Viewer

GET_VIEWERblock → hostrequest → replypage-only
payload
{
    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 → block
payload
{
    requestId: string;
    imageId: number;
    result: BlockImageScanResult;
}
OPEN_CHECKPOINT_PICKERblock → hostrequest → reply
payload
{
    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-only
payload
{
    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-only
payload
{
    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 → reply
payload
{
    requestId: string;
    versionId: number | null;
}
reply USER_CHECKPOINT_SET
{
    requestId: string;
    ok: boolean;
    error?: string;
}

Per-app storage

APP_STORAGE_DELETEblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
}
reply APP_STORAGE_DELETE_RESULT
{
    requestId: string;
    ok: boolean;
    deleted: boolean;
    error?: string;
}
APP_STORAGE_GETblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
}
reply APP_STORAGE_GET_RESULT
{
    requestId: string;
    value: unknown;
    error?: string;
}
APP_STORAGE_LISTblock → hostrequest → reply
payload
{
    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 → reply
payload
{
    requestId: string;
}
reply APP_STORAGE_QUOTA_RESULT
{
    requestId: string;
    usedBytes: number;
    rowCount: number;
    limitBytes: number;
    limitRows: number;
    error?: string;
}
APP_STORAGE_SETblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
    value: unknown;
}
reply APP_STORAGE_SET_RESULT
{
    requestId: string;
    ok: boolean;
    error?: string;
    sizeBytes?: number;
}

Shared storage

SHARED_APPENDblock → hostrequest → reply
payload
{
    requestId: string;
    value: SharedStorageValue;
}
reply SHARED_APPEND_RESULT
{
    requestId: string;
    key: string;
    error?: string;
}
SHARED_GET_COUNTblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
}
reply SHARED_GET_COUNT_RESULT
{
    requestId: string;
    count: number;
    error?: string;
}
SHARED_GET_COUNTSblock → hostrequest → reply
payload
{
    requestId: string;
    keys: string[];
}
reply SHARED_GET_COUNTS_RESULT
{
    requestId: string;
    counts: Record<string, number>;
    error?: string;
}
SHARED_LISTblock → hostrequest → reply
payload
{
    requestId: string;
    prefix?: string;
    limit?: number;
    cursor?: string;
}
reply SHARED_LIST_RESULT
{
    requestId: string;
    items: SharedStorageItemWire[];
    nextCursor?: string;
    error?: string;
}
SHARED_UNVOTEblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
}
reply SHARED_UNVOTE_RESULT
{
    requestId: string;
    count: number;
    error?: string;
}
SHARED_UPDATEblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
    value: SharedStorageValue;
}
reply SHARED_UPDATE_RESULT
{
    requestId: string;
    ok: boolean;
    error?: string;
}
SHARED_VOTEblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
}
reply SHARED_VOTE_RESULT
{
    requestId: string;
    count: number;
    error?: string;
}
SHARED_WITHDRAWblock → hostrequest → reply
payload
{
    requestId: string;
    key: string;
}
reply SHARED_WITHDRAW_RESULT
{
    requestId: string;
    ok: boolean;
    deleted: boolean;
    error?: string;
}

Wildcard packs

GET_WILDCARD_PACKblock → hostrequest → replypage-only
payload
{
    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.

Civitai Developer Documentation