Sending nested JSON using key/value UI (Postmark)

Hi all,

I’m trying to send the following data through HTTP node, but am having trouble figuring out how to send the nested data underneath TemplateModel. I keep getting a “Message received but incompatible JSON” message from Postmark.

I’ve tried a few approaches described in this post and this post, but they are for only one-key objects. I can’t figure out if I should use RAW or try to use the UI just without an expression (if I understand correctly, expressions are basically strings)

Below is the data I’m trying to send over HTTP node:

or as copyable code:

-d '{
  "From": "[email protected]",
  "To": "[email protected]",
  "TemplateAlias": "email-verification",
  "TemplateModel": {
    "company_url": "company_url_Value",
    "logo_url": "logo_url_Value",
    "greeting": "greeting_Value",
    "instructions": "instructions_Value",
    "code": "code_Value",
    "optional_instructions": "optional_instructions_Value",
    "salutation": "salutation_Value",
    "signature": "signature_Value",
    "company_name": "company_name_Value",
    "company_tagline": "company_tagline_Value",
    "subject": "subject_Value"
  }
}'

Check the example below:

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://webhook.site/d45c1b68-ecab-405e-8429-57cbec151fe5",
        "options": {},
        "bodyParametersUi": {
          "parameter": [
            {
              "name": "From",
              "value": "asasas"
            },
            {
              "name": "To",
              "value": "asasas"
            },
            {
              "name": "TemplateAlias",
              "value": "asasas"
            },
            {
              "name": "TemplateModel",
              "value": "={{{\n  \"company_url\": \"company_url_Value\",\n  \"logo_url\": \"logo_url_Value\",\n  \"greeting\": \"greeting_Value\",\n  \"instructions\": \"instructions_Value\",\n  \"code\": \"code_Value\",\n  \"optional_instructions\": \"optional_instructions_Value\",\n  \"salutation\": \"salutation_Value\",\n  \"signature\": \"signature_Value\",\n  \"company_name\": \"company_name_Value\",\n  \"company_tagline\": \"company_tagline_Value\",\n  \"subject\": \"subject_Value\"\n}}}"
            }
          ]
        }
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        530,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Hi @RicardoE105 - thank you! I’ve set it up like you sent, but it only returns this error once I plug in the values from the previous nodes:

This is what’s in the expression for the TemplateModel:

{{{
"company_url": "{{$node["Webhook"].json["query"]["website_url"]}}",
"logo_url": "{{$node["Webhook"].json["query"]["logo_url"]}}",
"greeting": "{{$node["Webhook"].json["query"]["greeting"]}}",
"instructions": "{{$node["Webhook"].json["query"]["instructions"]}}",
"code": "{{$node["Webhook"].json["query"]["code"]}}",
"optional_instructions": "{{$node["Webhook"].json["query"]["opt_instructions"]}}",
"salutation": "{{$node["Webhook"].json["query"]["salutation"]}}",
"signature": "{{$node["Webhook"].json["query"]["signature"]}}",
"company_name": "{{$node["Webhook"].json["query"]["company_name"]}}",
"company_tagline": "{{$node["Webhook"].json["query"]["company_tagline"]}}",
"subject": "{{$node["Webhook"].json["query"]["subject"]}}"
}}}

Check the example below:

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        500,
        300
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://webhook.site/d45c1b68-ecab-405e-8429-57cbec151fe5",
        "options": {},
        "bodyParametersUi": {
          "parameter": [
            {
              "name": "From",
              "value": "asasas"
            },
            {
              "name": "To",
              "value": "asasas"
            },
            {
              "name": "TemplateAlias",
              "value": "asasas"
            },
            {
              "name": "TemplateModel",
              "value": "={{{ \"active\": $evaluateExpression($node[\"Set\"].json[\"active\"] ) } }}"
            }
          ]
        }
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1000,
        300
      ]
    },
    {
      "parameters": {
        "values": {
          "boolean": [
            {
              "name": "active",
              "value": true
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        740,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

@pford also you can build the JSON before sending the HTTP Request using a set node. Check the example below:

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        320,
        300
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://webhook.site/d45c1b68-ecab-405e-8429-57cbec151fe5",
        "options": {},
        "bodyParametersUi": {
          "parameter": [
            {
              "name": "from",
              "value": "={{$node[\"Set\"].json[\"From\"]}}"
            },
            {
              "name": "to",
              "value": "={{$node[\"Set\"].json[\"To\"]}}"
            },
            {
              "name": "TemplateModel",
              "value": "={{$node[\"Set\"].json[\"TemplateModel\"]}}"
            }
          ]
        }
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1170,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "boolean": [],
          "string": [
            {
              "name": "From",
              "value": "={{$node[\"Function\"].json[\"From\"]}}"
            },
            {
              "name": "To",
              "value": "= {{$node[\"Function\"].json[\"To\"]}}"
            },
            {
              "name": "TemplateModel.company_url",
              "value": "={{$node[\"Function\"].json[\"company_url\"]}}"
            }
          ]
        },
        "options": {
          "dotNotation": true
        }
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        870,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [\n  {\n   json: {\n  \"From\": \"[email protected]\",\n  \"To\": \"[email protected]\",\n  \"TemplateAlias\": \"email-verification\",\n    \"company_url\": \"company_url_Value\",\n    \"logo_url\": \"logo_url_Value\",\n    \"greeting\": \"greeting_Value\",\n    \"instructions\": \"instructions_Value\",\n    \"code\": \"code_Value\",\n    \"optional_instructions\": \"optional_instructions_Value\",\n    \"salutation\": \"salutation_Value\",\n    \"signature\": \"signature_Value\",\n    \"company_name\": \"company_name_Value\",\n    \"company_tagline\": \"company_tagline_Value\",\n    \"subject\": \"subject_Value\"\n  } \n  }\n]"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        610,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

@RicardoE105 Might there be an easy way to do this for an array of items? I have this function node working in another workflow, but it’s only for single items, not for an array.

return [
  {
   json: {
  "appId": $node["Airtable"].json.fields["Adalo App ID"],
  "audience": { 
    "email": $node["Airtable"].json.fields["Recipient Email"] },
  "notification": {
    "titleText": $node["Airtable"].json.fields["Notification Title"],
    "bodyText": $node["Airtable"].json.fields["Notification Body"]
  }
  } 
  }
]

The loop would need to cycle through the items for each email. This is what I have so far but it doesn’t work quite right:

const users = items[0]

for (const user of users.json){ 

return [
  {
   json: {
  "appId": $node["Webhook"].json.query["app_id"],
  "audience": { 
    "email": $item(0).$node["Map Records1"].json["Email"] },
  "notification": {
    "titleText": $node["Webhook"].json.query["notify_title"],
    "bodyText": $node["Webhook"].json.query["notify_body"]
  }
  } 
  }
]
}

Sorry do not understand what you want to do and what you exactly iterate over because the code seems disconnected. To be able to really help you we would have to know how the input data looks like exactly.

Anyway, if you have really different items something like that should work:

return items.map(item => {
	return [
		{
			json: {
				"appId": item.json.query["app_id"],
				"audience": {
					"email": $item(0).$node["Map Records1"].json["Email"];
				},
				"notification": {
					"titleText": item.json.query["notify_title"],
					"bodyText": item.json.query["notify_body"]
				}
			}
		}
	]
});