API Execution Payloads

This guide documents how external systems interact with Guardian policy blocks through the REST API. It is the primary reference for integrators building MRV data pipelines, verification systems, or any application that submits data into a Guardian policy.

Overview

A Guardian policy is a directed graph of blocks. External systems interact with blocks through three patterns:

Pattern
Method
URL
When to use

Read block state

GET

/api/v1/policies/{policyId}/blocks/{blockId}

Get current form schema, document list, or block UI state

Submit data

POST

/api/v1/policies/{policyId}/blocks/{blockId}

Submit a form, trigger a button, select a role

Push external data

POST

/api/v1/external/{policyId}/{blockTag}

Push MRV/oracle data without a Guardian user session

Authentication

All block API calls require a JWT Bearer token from POST /api/v1/accounts/login.

Authorization: Bearer <jwt_token>

The calling user must have been assigned the appropriate role within the policy.


Standard Block Response Envelope

When calling GET /policies/{policyId}/blocks/{blockId}, Guardian returns a block-specific response. All responses share these common fields:

Field
Type
Description

id

string

Block UUID

blockType

string

Block type identifier from BlockType enum

policyId

string

Owning policy ID

readonly

boolean

Whether the calling user can submit data to this block

uiMetaData

object

Block-specific display configuration (title, description, type)


Block Data Submission Response

When calling POST /policies/{policyId}/blocks/{blockId} or POST /policies/{policyId}/tag/{tagName}/blocks, Guardian acknowledges the submission synchronously and returns a response that includes a trackingId for correlating the request with the async completion event.

Field
Type
Description

trackingId

string

UUID that uniquely identifies this block execution. Matches the trackingId in the external-events.block_complete event, allowing external systems to correlate requests with async outcomes without polling.

response

object

Present when history=true. The direct output of blockSetData.

result

object

Present when history=true. The final result from the last downstream step.

steps

array

Present when history=true. Ordered list of intermediate step results across the async execution chain. Empty array when history is not requested.

Example response (default):

Example response with history=true:

The submission response is returned as soon as the block accepts the data. The full async chain (IPFS uploads, HCS message submissions, downstream block execution) continues in the background and is reported via the external-events.block_complete event.


Block-Specific Payloads

requestVcDocumentBlock

Presents a data entry form based on a schema. The user fills the form and submits a VC document.

GET response — block state:

POST request — submit document:

Field
Type
Required
Description

document

object

Yes

VC document to submit

document.credentialSubject

array

Yes

Array with one object containing schema-defined fields

ref

string

No

Parent document ID for relationship linking


uploadVcDocumentBlock

Accepts file uploads or pre-built VC documents.

POST request:


interfaceDocumentsSourceBlock

Displays a list of documents to the user. Read-only; no POST required.

GET response:


buttonBlock

Displays action buttons that trigger workflow transitions (e.g., Approve/Reject).

GET response:

POST request — trigger a button:

Field
Type
Required
Description

document

object

Yes

The document to act on (must include id)

tag

string

Yes

Button tag to trigger — must match one of uiMetaData.buttons[].tag


policyRolesBlock

Assigns a role to the current user within the policy.

GET response:

POST request — select role:

Field
Type
Required
Description

role

string

Yes

Role name — must be one of the values in the GET response roles array


mintDocumentBlock

Mints environmental asset tokens after document approval. This is a server-side block (post: false, get: false) — it is triggered automatically by the policy engine when an upstream block fires a RunEvent. There is no direct GET or POST available from the API.

The block calculates a token amount by evaluating the configured rule expression against the incoming VC documents, creates a mint VC and VP, publishes both to HCS, and calls the Hedera token service to mint the tokens to the target account.

To observe mint outcomes, query the interfaceDocumentsSourceBlock that follows the mint block in the policy flow — documents there will carry a type of "MINT" once minting completes.


retirementDocumentBlock

Retires (wipes) tokens from a holder account. This is a server-side block (post: false, get: false) — it is triggered automatically by the policy engine when an upstream block fires a RunEvent. There is no direct GET or POST available from the API.

The block evaluates the configured rule expression (fungible tokens) or serial number expression (non-fungible tokens) against the incoming VC documents, creates a wipe VC and VP, publishes both to HCS, and calls the Hedera token wipe service.


createTokenBlock

Presents a token configuration form that allows a user to define and create a new Hedera token within the policy's token template. The block can also be set to autorun, in which case it creates the token automatically without user interaction.

GET response — token template:

Fields already locked by the policy template will be returned in data but cannot be overridden in the POST — submit only the fields the policy leaves editable.

POST request — submit token configuration:

Field
Type
Description

tokenName

string

Human-readable token name

tokenSymbol

string

Short token symbol (e.g. "iREC")

tokenType

string

"fungible" or "non-fungible"

decimals

string

Decimal precision for fungible tokens (e.g. "2")

initialSupply

string

Initial supply for fungible tokens (e.g. "0")

enableAdmin

boolean

Enables admin key on the token

changeSupply

boolean

Enables supply key (required for minting)

enableFreeze

boolean

Enables freeze key

enableKYC

boolean

Enables KYC key

enableWipe

boolean

Enables wipe key (required for retirement)

wipeContractId

string | null

Optional Hedera contract ID to use as wipe key

On success the block publishes the new token to HCS, stores the resulting tokenId in the policy document's tokens map, and fires a RunEvent to the next block.


tokenConfirmationBlock

Prompts the current user to associate (or dissociate) their Hedera account with a specific token, or to skip the step. This is required before a user can receive minted tokens.

GET response:

Field
Type
Description

action

string

"associate" or "dissociate" — the operation the user is being asked to confirm

accountId

string

The user's Hedera account ID that will be associated

tokenName

string

Display name of the token

tokenId

string

Hedera token ID to associate

POST request — confirm association:

POST request — skip:

Field
Type
Required
Description

action

string

Yes

"confirm" to proceed with the association/dissociation, "skip" to bypass

hederaAccountKey

string

Only when action is "confirm"

The user's Hedera ED25519 private key (hex or DER-encoded) used to sign the association transaction

Security note: hederaAccountKey is transmitted over HTTPS and used in-process to sign the Hedera association transaction. It is not stored by Guardian.


externalDataBlock

Receives data pushed from external systems. This is the block to target with POST /external/{policyId}/{blockTag}.

GET response:

External push via POST /api/v1/external/{policyId}/{blockTag}:

Field
Type
Required
Description

owner

string

Yes

DID of the document submitter

policyTag

string

Yes

Policy tag string (from policy configuration)

document

object

Yes

Full or partial VC document

document.credentialSubject

array

Yes

Array containing one credential subject with schema fields


reportBlock

Generates a trust chain / audit trail view. Read-only.

GET response:


switchBlock

Routes documents to different workflow paths based on conditions. Evaluated automatically by the policy engine — no external interaction required.


aggregateDocumentBlock

Collects multiple documents until a threshold is met, then batches them. Evaluated automatically.


calculateContainerBlock / mathBlock

Performs arithmetic on document fields. Evaluated automatically.


sendToGuardianBlock

Sends a document to the Hedera blockchain (IPFS + HCS). Evaluated automatically after form submission or approval.


External Data Submission API Reference

POST /api/v1/external/{policyId}/{blockTag}

The primary integration endpoint for external MRV systems, IoT sensors, and oracles.

Authentication: Not required for externalDataBlock configured as public. JWT required otherwise.

Path Parameters:

Parameter
Type
Required
Description

policyId

string

Yes

Policy MongoDB ID or published policy message ID

blockTag

string

Yes

Unique tag of the target externalDataBlock

Full Request Body Schema:

The proof field is optional — Guardian will sign the document if not provided.

Response 200 OK:

Error Codes:

Code
Description

400

Missing required fields

404

Policy or block tag not found

422

Document validation failed against policy schema

500

Internal server error


Tag-Based Block Access

Blocks can also be accessed by tag name instead of UUID:

This is useful when block UUIDs change between policy versions but tags remain stable.


Complete Integration Workflow

Step 1 — Authenticate

Step 2 — Find Published Policy

Locate the policy by name or policyTag in the response. Note its id.

Step 3 — Navigate to Roles Block

Find the policyRolesBlock in the block tree. Note its id.

Step 4 — Select Role

Step 5 — Get Submission Form Schema

Extract the schema.properties to determine which fields to populate.

Step 6 — Submit Document

The response includes a trackingId to correlate this submission with its async completion event:

Step 7 — Track Async Completion

Guardian processes block submissions asynchronously. IPFS uploads, HCS message submissions, and downstream blocks all run after the POST returns. There are two ways to observe completion:

Option A — Subscribe to external-events.block_complete (recommended)

Configure a webhook or SSE listener for the external-events.block_complete event. When the full async chain settles, Guardian emits:

Match the event's trackingId to the value returned in Step 6 to confirm your submission completed. When status is "failure", the error and errorDetails fields contain diagnostics.

Event field
Type
Description

trackingId

string

Matches the value returned by the POST response in Step 6

blockType

string

Block type that processed the submission

blockTag

string

Block tag identifier

blockId

string

Block UUID

policyId

string

Policy ID

userId

string

DID of the submitting user

status

string

"success" or "failure"

outputData

object

Optional. Direct output from blockSetData when available

error

string

Optional. Human-readable description of the first error (when status is "failure")

errorDetails

array

Optional. All errors collected across the async chain — each entry has message and optional stack

timestamp

number

Unix millisecond timestamp when completion was determined

Option B — Poll document status

Poll until data[0].option.status changes to APPROVED or REJECTED. Use this when you cannot configure an event listener.

Last updated

Was this helpful?