{ "kind": "open-flow-workflow", "version": 1, "name": "Extract Receipt Data from an Image URL", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_115bce1ba3dfce7c": { "name": "Enter the receipt URL", "kind": "start", "inputDefs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "receiptUrl" } ] }, "n_a9381fa5f103bb61": { "inputs": { "receiptUrl": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_115bce1ba3dfce7c", "output": "receiptUrl" } ] }, "modelId": { "kind": "value", "value": "YOUR_MINDEE_RECEIPT_MODEL_ID" } }, "name": "Prepare the receipt request", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "receiptUrl" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "modelId" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "modelId" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "body" } ], "name": "Prepare the receipt request", "moduleId": "n_47a9fd185229b600", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_902fc237eef566a2": { "inputs": { "url": { "kind": "value", "value": "https://api-v2.mindee.net/v2/products/extraction/enqueue" }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_a9381fa5f103bb61", "output": "body" } ] }, "header.Content-Type": { "kind": "value", "value": "multipart/form-data; boundary=openflow-mindee-form-7d1b8e6f" }, "auth.token": { "kind": "unset" } }, "name": "Submit the receipt to Mindee", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "header.Content-Type" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Submit the receipt to Mindee", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [ "Content-Type" ] }, "bodyFormat": "text", "authentication": { "type": "apiKey", "name": "Authorization", "in": "header" }, "responseFormat": "json", "statusPolicy": "all", "kind": "http-request" } } }, "n_b31b1b37ea759699": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_902fc237eef566a2", "output": "body" } ] }, "statusCode": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_902fc237eef566a2", "output": "statusCode" } ] }, "modelId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_a9381fa5f103bb61", "output": "modelId" } ] } }, "name": "Check the accepted job", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "modelId" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "jobId" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" } ], "name": "Check the accepted job", "moduleId": "n_1790a77db1f867b0", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_ef360ca56eebfaa7": { "inputs": {}, "name": "Wait for receipt processing", "kind": "wait", "inputDefinitions": [], "prompt": "Wait for receipt processing", "autoContinue": { "kind": "after", "durationMs": 3000 } }, "n_f4ff71e45fea58e7": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b31b1b37ea759699", "output": "url" } ] }, "auth.token": { "kind": "unset" } }, "name": "Check the Mindee job", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Check the Mindee job", "executor": { "method": "GET", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "apiKey", "name": "Authorization", "in": "header" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_5ce7e11c35854a33": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_f4ff71e45fea58e7", "output": "body" } ] }, "jobId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b31b1b37ea759699", "output": "jobId" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_5ce7e11c35854a33", "output": "state" } ] } }, "name": "Validate the job status", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "jobId" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previousState" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "ready" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "resultUrl" } ], "name": "Validate the job status", "moduleId": "n_ee3d8c8aea1067d7", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_5a553e53db05ffb2": { "inputs": {}, "name": "Is the receipt ready?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "ready", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_5ce7e11c35854a33", "output": "ready" } }, "operator": "isTrue" } ] } ] } ] }, "n_8321a85a8f23b7c4": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_5ce7e11c35854a33", "output": "resultUrl" } ] }, "auth.token": { "kind": "unset" } }, "name": "Read the receipt result", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Read the receipt result", "executor": { "method": "GET", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "apiKey", "name": "Authorization", "in": "header" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_038a9c1d05efddc5": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8321a85a8f23b7c4", "output": "body" } ] }, "jobId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b31b1b37ea759699", "output": "jobId" } ] } }, "name": "Check the receipt result", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "jobId" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "receipt" } ], "name": "Check the receipt result", "moduleId": "n_04f43e1704be97c2", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_d71c5bbcf0b1f92a": { "name": "Extracted receipt data", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "receipt" } ], "outputMappings": { "receipt": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_038a9c1d05efddc5", "output": "receipt" } ] } } } }, "edges": [ { "source": "n_115bce1ba3dfce7c", "target": "n_a9381fa5f103bb61" }, { "source": "n_a9381fa5f103bb61", "target": "n_902fc237eef566a2" }, { "source": "n_902fc237eef566a2", "target": "n_b31b1b37ea759699" }, { "source": "n_b31b1b37ea759699", "target": "n_ef360ca56eebfaa7" }, { "source": "n_ef360ca56eebfaa7", "target": "n_f4ff71e45fea58e7", "sourceHandle": "continue" }, { "source": "n_f4ff71e45fea58e7", "target": "n_5ce7e11c35854a33" }, { "source": "n_5ce7e11c35854a33", "target": "n_5a553e53db05ffb2" }, { "source": "n_5a553e53db05ffb2", "target": "n_8321a85a8f23b7c4", "sourceHandle": "ready" }, { "source": "n_5a553e53db05ffb2", "target": "n_ef360ca56eebfaa7", "sourceHandle": "otherwise" }, { "source": "n_8321a85a8f23b7c4", "target": "n_038a9c1d05efddc5" }, { "source": "n_038a9c1d05efddc5", "target": "n_d71c5bbcf0b1f92a" } ] } }, "modules": { "n_47a9fd185229b600": { "name": "Prepare the receipt request", "imports": [], "source": "export default function prepare({receiptUrl,modelId}){if(typeof receiptUrl!=='string'||!/^https:\\/\\/[^\\s/?#@]+(?:[/?#][^\\s]*)?$/i.test(receiptUrl)||receiptUrl.includes('openflow-mindee-form-7d1b8e6f'))throw Error('Enter a direct HTTPS receipt URL without credentials');if(typeof modelId!=='string'||!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(modelId))throw Error('Configure the Mindee Receipt model ID');const b='openflow-mindee-form-7d1b8e6f';return{modelId,body:`--${b}\\r\\nContent-Disposition: form-data; name=\"model_id\"\\r\\n\\r\\n${modelId}\\r\\n--${b}\\r\\nContent-Disposition: form-data; name=\"url\"\\r\\n\\r\\n${receiptUrl}\\r\\n--${b}--\\r\\n`}}\n" }, "n_1790a77db1f867b0": { "name": "Check the accepted job", "imports": [], "source": "export default function job({body,modelId,statusCode}){const j=body?.job;if(statusCode!==202||!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(j?.id??'')||j.model_id!==modelId)throw Error('Mindee returned an invalid job');return{jobId:j.id,url:`https://api-v2.mindee.net/v2/jobs/${j.id}?redirect=false`}}\n" }, "n_ee3d8c8aea1067d7": { "name": "Validate the job status", "imports": [], "source": "export default function status({body,jobId,previousState}){const attempt=(previousState?.attempt??0)+1,j=body?.job;if(!Number.isInteger(attempt)||attempt>200||j?.id!==jobId)throw Error('Invalid Mindee job status');if(j.status==='Failed')throw Error('Mindee receipt processing failed');if(j.status==='Processing'){if(attempt>=200)throw Error('Mindee did not finish within the polling window');return{state:{attempt},ready:false,resultUrl:'https://api-v2.mindee.net/v2/products/extraction/results/unused'}}if(j.status!=='Processed'||!/^https:\\/\\/api-v2\\.mindee\\.net\\/v2\\/products\\/extraction\\/results\\/[0-9a-f-]{36}$/i.test(j.result_url??''))throw Error('Invalid Mindee result URL');return{state:{attempt},ready:true,resultUrl:j.result_url}}\n" }, "n_04f43e1704be97c2": { "name": "Check the receipt result", "imports": [], "source": "export default function result({body,jobId}){if(!body||typeof body!=='object'||Array.isArray(body)||body.inference?.job?.id!==jobId||!body.inference?.result?.fields||typeof body.inference.result.fields!=='object')throw Error('Mindee returned an invalid receipt result');return{receipt:body}}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }