The main difference between the declarative and programmatic styles is how they handle incoming data and build API requests. The programmatic style requires an execute() method, which reads incoming data and parameters, then builds a request. The declarative style handles this using the routing key in the operations object. Refer to Node base file for more information on node parameters and the execute() method.
To understand the difference between the declarative and programmatic styles, compare the two code snippets below. This example creates a simplified version of the SendGrid integration, called "FriendGrid." The following code snippets aren't complete: they emphasize the differences in the node building styles.
import{IExecuteFunctions}from'n8n-core';import{INodeExecutionData,INodeType,INodeTypeDescription}from'n8n-workflow';// Create the FriendGrid classexportclassFriendGridimplementsINodeType{description:INodeTypeDescription={displayName:'FriendGrid',name:'friendGrid',...properties:[{displayName:'Resource',...},{displayName:'Operation',name:'operation',type:'options',displayOptions:{show:{resource:['contact',],},},options:[{name:'Create',value:'create',description:'Create a contact',},],default:'create',description:'The operation to perform.',},{displayName:'Email',name:'email',...},{displayName:'Additional Fields',// Sets up optional fields},],};asyncexecute(this:IExecuteFunctions):Promise<INodeExecutionData[][]>{letresponseData;constresource=this.getNodeParameter('resource',0)asstring;constoperation=this.getNodeParameter('operation',0)asstring;//Get credentials the user provided for this nodeconstcredentials=awaitthis.getCredentials('friendGridApi')asIDataObject;if(resource==='contact'){if(operation==='create'){// Get email inputconstemail=this.getNodeParameter('email',0)asstring;// Get additional fields inputconstadditionalFields=this.getNodeParameter('additionalFields',0)asIDataObject;constdata:IDataObject={email,};Object.assign(data,additionalFields);// Make HTTP request as defined in https://sendgrid.com/docs/api-reference/constoptions:OptionsWithUri={headers:{'Accept':'application/json','Authorization':`Bearer ${credentials.apiKey}`,},method:'PUT',body:{contacts:[data,],},url:`https://api.sendgrid.com/v3/marketing/contacts`,json:true,};responseData=awaitthis.helpers.httpRequest(options);}}// Map data to n8n datareturn[this.helpers.returnJsonArray(responseData)];}}
import{INodeType,INodeTypeDescription}from'n8n-workflow';// Create the FriendGrid classexportclassFriendGridimplementsINodeType{description:INodeTypeDescription={displayName:'FriendGrid',name:'friendGrid',...// Set up the basic request configurationrequestDefaults:{baseURL:'https://api.sendgrid.com/v3/marketing'},properties:[{displayName:'Resource',...},{displayName:'Operation',name:'operation',type:'options',displayOptions:{show:{resource:['contact',],},},options:[{name:'Create',value:'create',description:'Create a contact',// Add the routing objectrouting:{request:{method:'POST',url:'=/contacts',send:{type:'body',properties:{email:{{$parameter["email"]}}}}}},// Handle the response to contact creationoutput:{postReceive:[{type:'set',properties:{value:'={{ { "success": $response } }}'}}]}},],default:'create',description:'The operation to perform.',},{displayName:'Email',...},{displayName:'Additional Fields',// Sets up optional fields},],}// No execute method needed}