diff --git a/packages/nodes-base/credentials/AirtableApi.credentials.ts b/packages/nodes-base/credentials/AirtableApi.credentials.ts
index 09eee15b4c..857ce45eaa 100644
--- a/packages/nodes-base/credentials/AirtableApi.credentials.ts
+++ b/packages/nodes-base/credentials/AirtableApi.credentials.ts
@@ -8,6 +8,13 @@ export class AirtableApi implements ICredentialType {
documentationUrl = 'airtable';
properties: INodeProperties[] = [
+ {
+ displayName:
+ 'API Keys will be deprecated by the end of January 2024, see this article for more details. We recommend to use Personal Access Token instead.',
+ name: 'deprecated',
+ type: 'notice',
+ default: '',
+ },
{
displayName: 'API Key',
name: 'apiKey',
diff --git a/packages/nodes-base/credentials/AirtableTokenApi.credentials.ts b/packages/nodes-base/credentials/AirtableTokenApi.credentials.ts
new file mode 100644
index 0000000000..b63a80d236
--- /dev/null
+++ b/packages/nodes-base/credentials/AirtableTokenApi.credentials.ts
@@ -0,0 +1,39 @@
+import type {
+ IAuthenticateGeneric,
+ ICredentialTestRequest,
+ ICredentialType,
+ INodeProperties,
+} from 'n8n-workflow';
+
+export class AirtableTokenApi implements ICredentialType {
+ name = 'airtableTokenApi';
+
+ displayName = 'Airtable Personal Access Token API';
+
+ documentationUrl = 'airtable';
+
+ properties: INodeProperties[] = [
+ {
+ displayName: 'Access Token',
+ name: 'accessToken',
+ type: 'string',
+ typeOptions: { password: true },
+ default: '',
+ },
+ ];
+
+ authenticate: IAuthenticateGeneric = {
+ type: 'generic',
+ properties: {
+ headers: {
+ Authorization: '=Bearer {{$credentials.accessToken}}',
+ },
+ },
+ };
+
+ test: ICredentialTestRequest = {
+ request: {
+ baseURL: 'https://api.airtable.com/v0/meta/whoami',
+ },
+ };
+}
diff --git a/packages/nodes-base/nodes/Airtable/Airtable.node.ts b/packages/nodes-base/nodes/Airtable/Airtable.node.ts
index eb8d499b32..49c5491976 100644
--- a/packages/nodes-base/nodes/Airtable/Airtable.node.ts
+++ b/packages/nodes-base/nodes/Airtable/Airtable.node.ts
@@ -27,9 +27,39 @@ export class Airtable implements INodeType {
{
name: 'airtableApi',
required: true,
+ displayOptions: {
+ show: {
+ authentication: ['airtableApi'],
+ },
+ },
+ },
+ {
+ name: 'airtableTokenApi',
+ required: true,
+ displayOptions: {
+ show: {
+ authentication: ['airtableTokenApi'],
+ },
+ },
},
],
properties: [
+ {
+ displayName: 'Authentication',
+ name: 'authentication',
+ type: 'options',
+ options: [
+ {
+ name: 'API Key',
+ value: 'airtableApi',
+ },
+ {
+ name: 'Access Token',
+ value: 'airtableTokenApi',
+ },
+ ],
+ default: 'airtableApi',
+ },
{
displayName: 'Operation',
name: 'operation',
@@ -546,14 +576,15 @@ export class Airtable implements INodeType {
delete (row.fields as any).id;
} else {
// Add only the specified fields
- row.fields = {} as IDataObject;
+ const rowFields: IDataObject = {};
fields = this.getNodeParameter('fields', i, []) as string[];
for (const fieldName of fields) {
- // @ts-ignore
- row.fields[fieldName] = items[i].json[fieldName];
+ rowFields[fieldName] = items[i].json[fieldName];
}
+
+ row.fields = rowFields;
}
rows.push(row);
@@ -761,10 +792,12 @@ export class Airtable implements INodeType {
} else {
fields = this.getNodeParameter('fields', i, []) as string[];
+ const rowFields: IDataObject = {};
for (const fieldName of fields) {
- // @ts-ignore
- row.fields[fieldName] = items[i].json[fieldName];
+ rowFields[fieldName] = items[i].json[fieldName];
}
+
+ row.fields = rowFields;
}
row.id = this.getNodeParameter('id', i) as string;
diff --git a/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts b/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts
index b54ae8f8da..ce3b868c4f 100644
--- a/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts
+++ b/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts
@@ -28,12 +28,42 @@ export class AirtableTrigger implements INodeType {
{
name: 'airtableApi',
required: true,
+ displayOptions: {
+ show: {
+ authentication: ['airtableApi'],
+ },
+ },
+ },
+ {
+ name: 'airtableTokenApi',
+ required: true,
+ displayOptions: {
+ show: {
+ authentication: ['airtableTokenApi'],
+ },
+ },
},
],
polling: true,
inputs: [],
outputs: ['main'],
properties: [
+ {
+ displayName: 'Authentication',
+ name: 'authentication',
+ type: 'options',
+ options: [
+ {
+ name: 'API Key',
+ value: 'airtableApi',
+ },
+ {
+ name: 'Access Token',
+ value: 'airtableTokenApi',
+ },
+ ],
+ default: 'airtableApi',
+ },
{
displayName: 'Base',
name: 'baseId',
@@ -192,19 +222,14 @@ export class AirtableTrigger implements INodeType {
async poll(this: IPollFunctions): Promise {
const downloadAttachments = this.getNodeParameter('downloadAttachments', 0) as boolean;
-
const webhookData = this.getWorkflowStaticData('node');
+ const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
+ const base = this.getNodeParameter('baseId', '', { extractValue: true }) as string;
+ const table = this.getNodeParameter('tableId', '', { extractValue: true }) as string;
+ const triggerField = this.getNodeParameter('triggerField') as string;
const qs: IDataObject = {};
- const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
-
- const base = this.getNodeParameter('baseId', '', { extractValue: true }) as string;
-
- const table = this.getNodeParameter('tableId', '', { extractValue: true }) as string;
-
- const triggerField = this.getNodeParameter('triggerField') as string;
-
const endpoint = `${base}/${table}`;
const now = moment().utc().format();
diff --git a/packages/nodes-base/nodes/Airtable/GenericFunctions.ts b/packages/nodes-base/nodes/Airtable/GenericFunctions.ts
index 80e769e18a..3b2b3c7b61 100644
--- a/packages/nodes-base/nodes/Airtable/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/Airtable/GenericFunctions.ts
@@ -58,8 +58,8 @@ export async function apiRequest(
if (Object.keys(body).length === 0) {
delete options.body;
}
-
- return this.helpers.requestWithAuthentication.call(this, 'airtableApi', options);
+ const authenticationMethod = this.getNodeParameter('authentication', 0) as string;
+ return this.helpers.requestWithAuthentication.call(this, authenticationMethod, options);
}
/**
diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json
index c4c6304725..601071be46 100644
--- a/packages/nodes-base/package.json
+++ b/packages/nodes-base/package.json
@@ -39,6 +39,7 @@
"dist/credentials/AffinityApi.credentials.js",
"dist/credentials/AgileCrmApi.credentials.js",
"dist/credentials/AirtableApi.credentials.js",
+ "dist/credentials/AirtableTokenApi.credentials.js",
"dist/credentials/Amqp.credentials.js",
"dist/credentials/ApiTemplateIoApi.credentials.js",
"dist/credentials/AsanaApi.credentials.js",