diff --git a/packages/nodes-base/nodes/Airtable/Airtable.node.ts b/packages/nodes-base/nodes/Airtable/Airtable.node.ts
index 20e62b4e5c..4f15041474 100644
--- a/packages/nodes-base/nodes/Airtable/Airtable.node.ts
+++ b/packages/nodes-base/nodes/Airtable/Airtable.node.ts
@@ -75,12 +75,12 @@ export class Airtable implements INodeType {
// All
// ----------------------------------
{
- displayName: 'Application ID',
+ displayName: 'Base ID',
name: 'application',
type: 'string',
default: '',
required: true,
- description: 'The ID of the application to access.',
+ description: 'The ID of the base to access.',
},
{
displayName: 'Table',
diff --git a/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts b/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts
new file mode 100644
index 0000000000..0340e5fcac
--- /dev/null
+++ b/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts
@@ -0,0 +1,154 @@
+import {
+ IPollFunctions,
+} from 'n8n-core';
+
+import {
+ IDataObject,
+ INodeExecutionData,
+ INodeType,
+ INodeTypeDescription,
+} from 'n8n-workflow';
+
+import {
+ apiRequestAllItems,
+} from './GenericFunctions';
+
+import * as moment from 'moment';
+
+export class AirtableTrigger implements INodeType {
+ description: INodeTypeDescription = {
+ displayName: 'Airtable Trigger',
+ name: 'airtableTrigger',
+ icon: 'file:airtable.png',
+ group: ['trigger'],
+ version: 1,
+ description: 'Starts the workflow when Airtable events occur',
+ subtitle: '={{$parameter["event"]}}',
+ defaults: {
+ name: 'Airtable Trigger',
+ color: '#445599',
+ },
+ credentials: [
+ {
+ name: 'airtableApi',
+ required: true,
+ },
+ ],
+ polling: true,
+ inputs: [],
+ outputs: ['main'],
+ properties: [
+ {
+ displayName: 'Base ID',
+ name: 'baseId',
+ type: 'string',
+ default: '',
+ required: true,
+ description: 'The ID of this base.',
+ },
+ {
+ displayName: 'Table',
+ name: 'tableId',
+ type: 'string',
+ default: '',
+ description: 'The name of table to access.',
+ required: true,
+ },
+ {
+ displayName: 'Trigger Field',
+ name: 'triggerField',
+ type: 'string',
+ default: '',
+ description: `A Created Time or Last Modified Time field that will be used to sort records.
+ If you do not have a Created Time or Last Modified Time field in your schema, please create one,
+ because without this field trigger will not work correctly.`,
+ required: true,
+ },
+ {
+ displayName: 'Additional Fields',
+ name: 'additionalFields',
+ type: 'collection',
+ placeholder: 'Add Field',
+ default: {},
+ options: [
+ {
+ displayName: 'Fields',
+ name: 'fields',
+ type: 'string',
+ default: '',
+ description: `Fields to be included in the response.
+ Multiple ones can be set separated by comma. Example: name,id.
+ By default just the trigger field will be included.`,
+ },
+ {
+ displayName: 'Formula',
+ name: 'formula',
+ type: 'string',
+ default: '',
+ description: '',
+ },
+ {
+ displayName: 'View ID',
+ name: 'viewId',
+ type: 'string',
+ default: '',
+ description: '',
+ },
+ ],
+ },
+ ],
+ };
+
+ async poll(this: IPollFunctions): Promise {
+
+ const webhookData = this.getWorkflowStaticData('node');
+
+ const qs: IDataObject = {};
+
+ const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
+
+ const base = this.getNodeParameter('baseId') as string;
+
+ const table = this.getNodeParameter('tableId') as string;
+
+ const triggerField = this.getNodeParameter('triggerField') as string;
+
+ const endpoint = `${base}/${table}`;
+
+ const now = moment().utc().format();
+
+ const startDate = webhookData.lastTimeChecked as string || now;
+
+ const endDate = now;
+
+ if (additionalFields.viewId) {
+ qs.view = additionalFields.viewId;
+ }
+
+ if (additionalFields.fields) {
+ qs['fields[]'] = (additionalFields.fields as string).split(',');
+ }
+
+ qs.filterByFormula = `IS_AFTER({${triggerField}}, DATETIME_PARSE("${startDate}", "YYYY-MM-DD HH:mm:ss"))`;
+
+ if (additionalFields.formula) {
+ qs.filterByFormula = `AND(${qs.filterByFormula}, ${additionalFields.formula})`;
+ }
+
+ if (this.getMode() === 'manual') {
+ delete qs.filterByFormula;
+ qs.maxRecords = 1;
+ }
+
+ const { records } = await apiRequestAllItems.call(this, 'GET', endpoint, {}, qs);
+
+ webhookData.lastTimeChecked = endDate;
+
+ if (Array.isArray(records) && records.length) {
+
+ return [this.helpers.returnJsonArray(records)];
+ }
+
+ return null;
+ }
+}
diff --git a/packages/nodes-base/nodes/Airtable/GenericFunctions.ts b/packages/nodes-base/nodes/Airtable/GenericFunctions.ts
index 6a0e688f49..09be7c40bd 100644
--- a/packages/nodes-base/nodes/Airtable/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/Airtable/GenericFunctions.ts
@@ -12,6 +12,7 @@ import {
IBinaryKeyData,
IDataObject,
INodeExecutionData,
+ IPollFunctions,
} from 'n8n-workflow';
@@ -36,7 +37,7 @@ export interface IRecord {
* @param {object} body
* @returns {Promise}
*/
-export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: object, query?: IDataObject, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any
+export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IPollFunctions, method: string, endpoint: string, body: object, query?: IDataObject, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any
const credentials = this.getCredentials('airtableApi');
if (credentials === undefined) {
@@ -104,7 +105,7 @@ export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoa
* @param {IDataObject} [query]
* @returns {Promise}
*/
-export async function apiRequestAllItems(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject): Promise { // tslint:disable-line:no-any
+export async function apiRequestAllItems(this: IHookFunctions | IExecuteFunctions | IPollFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject): Promise { // tslint:disable-line:no-any
if (query === undefined) {
query = {};
diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json
index e2c4f39c14..df04dbf5ed 100644
--- a/packages/nodes-base/package.json
+++ b/packages/nodes-base/package.json
@@ -225,6 +225,7 @@
"dist/nodes/ActiveCampaign/ActiveCampaignTrigger.node.js",
"dist/nodes/AgileCrm/AgileCrm.node.js",
"dist/nodes/Airtable/Airtable.node.js",
+ "dist/nodes/Airtable/AirtableTrigger.node.js",
"dist/nodes/AcuityScheduling/AcuitySchedulingTrigger.node.js",
"dist/nodes/Amqp/Amqp.node.js",
"dist/nodes/Amqp/AmqpTrigger.node.js",