The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Institution - Batch Credential Issuance - FIXED",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "batch-issue-acledger-v1",
"options": {}
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{$json.headers[\"x-acl-auth-key\"]}}",
"operation": "equal",
"value2": "={{$env.ACL_AUTH_KEY}}"
}
]
}
},
"name": "Security Guard",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
200,
0
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "{\"error\": \"Unauthorized\", \"message\": \"Invalid security token\"}",
"options": {
"responseCode": 401
}
},
"name": "Reject Request",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
200,
200
]
},
{
"parameters": {
"fieldToSplitOut": "credentials"
},
"name": "Split Credentials",
"type": "n8n-nodes-base.itemLists",
"typeVersion": 1,
"position": [
400,
0
]
},
{
"parameters": {
"jsCode": "const item = $json || {};\nconst nowIso = new Date().toISOString();\n\nconst computeUniqueHash = (ipfsURI) => {\n const link = String(ipfsURI || '').trim();\n if (!link) return `hash-${Date.now()}`;\n try {\n const crypto = require('crypto');\n return 'hash-' + crypto.createHash('sha256').update(link).digest('hex');\n } catch (e) {\n let h = 0;\n for (let i = 0; i < link.length; i++) {\n h = ((h << 5) - h) + link.charCodeAt(i);\n h |= 0;\n }\n return 'hash-fallback-' + Math.abs(h).toString(16);\n }\n};\n\nconst makeDoc = (i = {}) => {\n const tokenId = String(i.tokenId || ('0.0.' + (Math.floor(Math.random() * 9000000) + 1000000)));\n const serialNumber = String(i.serialNumber || '1');\n const universityId = i.universityId || null;\n const studentAccountId = (i.studentAccountId === undefined) ? null : i.studentAccountId;\n const ipfsURI = i.ipfsURI || 'ipfs://QmTest';\n const uniqueHash = i.uniqueHash || computeUniqueHash(ipfsURI);\n const ext = i.externalProofs || {};\n const externalProofs = {\n hederaTx: ext.hederaTx || null,\n xrpTxHash: ext.xrpTxHash || null,\n algoTxId: ext.algoTxId || null\n };\n return {\n tokenId,\n serialNumber,\n universityId,\n studentAccountId,\n uniqueHash,\n ipfsURI,\n externalProofs,\n createdAt: nowIso,\n updatedAt: nowIso,\n __v: 0\n };\n};\n\nreturn { json: makeDoc(item) };"
},
"name": "Build Credential Docs",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [
600,
0
]
},
{
"parameters": {
"operation": "insert",
"collection": "issued_credentials",
"options": {}
},
"name": "Save to Mongo",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1,
"position": [
800,
0
],
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "aggregateItems",
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "uniqueHash",
"renameField": "hashes"
},
{
"fieldToAggregate": "tokenId",
"renameField": "tokenIds"
}
]
}
},
"name": "Aggregate Results",
"type": "n8n-nodes-base.itemLists",
"typeVersion": 1,
"position": [
1000,
0
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "{\n \"success\": true,\n \"message\": \"Batch processed successfully\",\n \"count\": {{$json.hashes.length}},\n \"hashes\": {{$json.hashes}},\n \"tokenIds\": {{$json.tokenIds}}\n}",
"options": {}
},
"name": "Respond to App",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1200,
0
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Security Guard",
"type": "main",
"index": 0
}
]
]
},
"Security Guard": {
"main": [
[
{
"node": "Split Credentials",
"type": "main",
"index": 0
}
],
[
{
"node": "Reject Request",
"type": "main",
"index": 0
}
]
]
},
"Split Credentials": {
"main": [
[
{
"node": "Build Credential Docs",
"type": "main",
"index": 0
}
]
]
},
"Build Credential Docs": {
"main": [
[
{
"node": "Save to Mongo",
"type": "main",
"index": 0
}
]
]
},
"Save to Mongo": {
"main": [
[
{
"node": "Aggregate Results",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Results": {
"main": [
[
{
"node": "Respond to App",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
mongoDb
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Institution - Batch Credential Issuance - FIXED. Uses itemLists, mongoDb. Webhook trigger; 8 nodes.
Source: https://github.com/Aether-Connect-Labs/AcademicChain-Ledger/blob/main/n8n/workflows/batch-issue.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
BP_check. Uses googleSheets, @n-octo-n/n8n-nodes-json-database, httpRequest, itemLists. Webhook trigger; 99 nodes.
BP_check2. Uses googleSheets, @n-octo-n/n8n-nodes-json-database, httpRequest, itemLists. Webhook trigger; 95 nodes.
This workflow automates raw materials inventory management for businesses, eliminating manual stock updates, delayed material issue approvals, and missed low stock alerts. It ensures real-time stock t
Orquestador Multichain AcademicChain. Uses httpRequest, moveBinaryData, mongoDb. Webhook trigger; 23 nodes.
Enhance your support documentation with an audio-first experience. This workflow converts Supabase FAQ entries into high-quality audio using Google Cloud TTS, hosts them via a CDN, and embeds them int