External Events
Guardian processes tasks asynchronously. As operations complete, it publishes events to an internal NATS message broker. External systems can subscribe to these events to build reliable, event-driven integrations without polling.
There are two ways to consume Guardian events:
Direct NATS subscription — connect your own NATS client to the same broker and subscribe to subjects directly.
Application Events Module — a standalone HTTP service (port 3012) that subscribes to NATS on your behalf and forwards events to registered webhooks or a streaming endpoint. See Application Events Module.
Subscription Patterns
Guardian events use two NATS interaction patterns.
Publish / Subscribe
Events with pattern type publish follow the standard pub/sub model. The same message is delivered to every active subscriber. If multiple subscribers are running, ensure your application handles potential duplicate delivery.
import { connect, JSONCodec } from "nats";
(async () => {
const nc = await connect({ servers: "localhost:4222" });
const c = JSONCodec();
const sub = nc.subscribe("external-events.token_minted");
(async () => {
for await (const m of sub) {
console.log(`[${sub.getProcessed()}]`, c.decode(m.data));
}
console.log("subscription closed");
})();
})();For more details see the NATS.js publish/subscribe documentation.
Request / Reply
Events with pattern type request require the subscriber to reply. Guardian waits for your response before proceeding. If no listener is registered, or the listener responds with an error, Guardian continues with the original content unmodified.
This pattern is used for IPFS content interception hooks (e.g., encryption/decryption of content before upload or after read).
Event Reference
Core External Events
These events are published by Guardian's core services and represent the primary integration surface for external systems.
external-events.token_minted
publish
A Hedera token was successfully minted
external-events.token_mint_complete
publish
All token minting operations for a batch are complete
external-events.error_logs
publish
An error was written to the Guardian logger service
external-events.block_event
publish
A policy block execution event occurred
external-events.block_complete
publish
Full async execution chain for a block data call has settled
external-events.ipfs_added_file
publish
A file was successfully added to IPFS
external-events.ipfs_before_upload_content
request
Hook: intercept and optionally transform content before IPFS upload
external-events.ipfs_after_read_content
request
Hook: intercept and optionally transform content after reading from IPFS
external-events.ipfs_loaded_file
subscribe
A file load from IPFS has completed
external-events.token_minted
external-events.token_mintedPattern: publish
Trigger: Guardian successfully mints a Hedera token during policy execution.
Payload:
tokenId
string
Hedera token identifier (shard.realm.num)
tokenValue
number
Number of tokens minted in this operation
memo
string
Optional memo string associated with the mint transaction
external-events.token_mint_complete
external-events.token_mint_completePattern: publish
Trigger: All pending token minting operations in a batch have completed.
Payload:
tokenValue
number
Total number of tokens that were minted in the completed batch
external-events.error_logs
external-events.error_logsPattern: publish
Trigger: An error is written to the Guardian logger service by any internal service.
Payload:
message
string
Human-readable error description
type
string
Severity or error category
attributes
object
Additional contextual attributes from the originating service
external-events.block_event
external-events.block_eventPattern: publish
Trigger: A policy block executes an action that produces an external event (e.g., a user submits a form, a document is set, a timer fires).
Payload:
The payload is an array of block event objects. Each object has:
type
string
Event type — one of Run, Set, TickAggregate, TickCron, DeleteMember, StartCron, StopCron, SignatureQuorumReachedEvent, SignatureSetInsufficientEvent, Step, Chunk
blockUUID
string
Unique identifier of the block that produced this event
blockType
string
The block's type name (e.g., requestVcDocumentBlock, mintDocumentBlock)
blockTag
string
The human-readable tag assigned to the block in the policy editor
userId
string
Hedera DID of the user who triggered the block action
data
object
Block-specific payload; structure varies by block type
external-events.block_complete
external-events.block_completePattern: publish
Trigger: Triggered when the full async execution chain (downstream blocks, IPFS uploads, Hedera message submissions) for a SET_BLOCK_DATA / SET_BLOCK_DATA_BY_TAG call has settled — success or failure. The trackingId field matches the value returned in the API response, so external systems can correlate the event with their request without polling.
Payload:
trackingId
string
UUID correlating this event to the originating API call
blockType
string
The block's type name
blockTag
string
The human-readable tag assigned to the block in the policy editor
blockId
string
Unique identifier of the block
policyId
string
Identifier of the policy containing the block
userId
string
Hedera DID of the user whose action triggered the chain
status
string
success or failure
timestamp
number
Unix epoch milliseconds when the chain settled
external-events.ipfs_added_file
external-events.ipfs_added_filePattern: publish
Trigger: A file (document, schema, artifact) is successfully pinned to IPFS.
Payload:
cid
string
IPFS content identifier (CIDv0)
url
string
IPFS URI in ipfs:// scheme
external-events.ipfs_before_upload_content
external-events.ipfs_before_upload_contentPattern: request/reply
Trigger: Guardian is about to upload content to IPFS. The content is delivered as a base64-encoded buffer.
Payload received:
Expected reply:
Return a zlib-deflated JSON object with the (optionally transformed) content:
To skip transformation and signal an error, respond with:
If no listener is registered, or the listener responds with an error, Guardian uploads the original content unchanged.
Note: This event is a request/reply hook. It is not forwarded by the Application Events Module. Subscribe directly via NATS.
external-events.ipfs_after_read_content
external-events.ipfs_after_read_contentPattern: request/reply
Trigger: Guardian has just read content from IPFS. Use this hook to decrypt or post-process content before Guardian consumes it.
Payload received:
Expected reply: Same structure as ipfs_before_upload_content. Return the transformed content or an error object.
Note: This event is a request/reply hook. It is not forwarded by the Application Events Module. Subscribe directly via NATS.
external-events.ipfs_loaded_file
external-events.ipfs_loaded_filePattern: subscribe
Trigger: An asynchronous IPFS file load has completed (either successfully or with an error).
Payload:
taskId
string
UUID correlating this result to the original load request
fileContent
string
Base64-encoded file content; present on success
error
string | null
Error message if the load failed; null on success
Note: This event is not forwarded by the Application Events Module. Subscribe directly via NATS.
Policy Engine Events
In addition to the core external events above, the Application Events Module also surfaces Guardian's internal policy coordination events. These are emitted on NATS subjects from the PolicyEvents and PolicyEngineEvents enumerations (e.g., policy-event-policy-ready, policy-engine-event-publish-policies).
These events are intended for advanced integrations that need to react to specific policy lifecycle transitions. They are available through the Application Events Module's streaming endpoint and webhook registration. Use GET /api/events on the Application Events Module to retrieve the complete list of exposed event subjects at runtime.
Reference Implementation
A complete Node.js reference client demonstrating publish/subscribe and request/reply patterns (including IPFS content encryption) is available at:
Last updated
Was this helpful?