n8n-syntax-credentials

Installation
SKILL.md

n8n-syntax-credentials

Quick Reference

ICredentialType Interface

Property Type Required Description
name string YES Internal identifier (e.g., 'myServiceApi')
displayName string YES GUI label shown to users
documentationUrl string NO Link to credentials setup docs
properties INodeProperties[] YES Array of credential input fields
authenticate IAuthenticate NO How credentials inject into requests
test ICredentialTestRequest NO Endpoint for credential validation
extends string[] NO Inherit from other credential types
icon Icon NO Credential icon in GUI
iconUrl string NO URL-based icon

Credential Property Types

Type Use Case Example
'string' API keys, tokens, URLs { type: 'string', typeOptions: { password: true } }
'number' Port numbers, numeric IDs { type: 'number', default: 443 }
'boolean' Feature toggles { type: 'boolean', default: false }
'options' Region selectors, auth method { type: 'options', options: [...] }
'hidden' Internal values, computed tokens { type: 'hidden', typeOptions: { expirable: true } }

authenticate: 4 Injection Methods

Method Target Key in properties
Query string URL parameters qs
Header HTTP headers headers
Request body POST body body
Basic auth Authorization header auth

ALL methods require type: 'generic' as the authenticate type.

Credential Expression Syntax

Access credential values inside authenticate using: ={{$credentials.fieldName}}

For header values with prefixes: '=Bearer {{$credentials.apiKey}}'

Critical Warnings

ALWAYS set typeOptions: { password: true } on sensitive fields (API keys, tokens, passwords) -- n8n masks these in the GUI and encrypts them at rest.

ALWAYS register credentials in package.json under the n8n.credentials array pointing to compiled .js files in dist/.

ALWAYS use type: 'generic' in the authenticate property -- no other type value is supported for the generic authenticate pattern.

ALWAYS provide a test property with a lightweight API endpoint to validate credentials during setup.

NEVER store credentials in plain text or workflow JSON -- n8n encrypts all credential data using an encryption key.

NEVER hardcode credential values in node code -- ALWAYS read them via this.getCredentials('credentialTypeName') in the node's execute method.

NEVER use authenticate AND manually inject credentials in the node's execute() method for the same credential -- pick one approach.

NEVER forget the = prefix in authenticate expressions -- '={{$credentials.key}}' is correct, '{{$credentials.key}}' silently passes a literal string.


Decision Tree: Which Authentication Pattern?

Need authentication?
├── API key in URL parameter?
│   └── Use authenticate.properties.qs
├── API key or token in header?
│   └── Use authenticate.properties.headers
├── Username + password (Basic Auth)?
│   └── Use authenticate.properties.auth
├── Credentials in request body?
│   └── Use authenticate.properties.body
├── OAuth2 flow?
│   └── Extend 'oAuth2Api' base credential
└── Complex/custom auth logic?
    └── Skip authenticate, handle in node execute() via this.getCredentials()

Essential Patterns

Pattern 1: API Key Credential (Header Injection)

import type { ICredentialType, INodeProperties, IAuthenticate } from 'n8n-workflow';

export class ExampleApi implements ICredentialType {
  name = 'exampleApi';
  displayName = 'Example API';
  documentationUrl = 'https://docs.example.com/auth';
  properties: INodeProperties[] = [
    {
      displayName: 'API Key',
      name: 'apiKey',
      type: 'string',
      typeOptions: { password: true },
      default: '',
    },
  ];
  authenticate: IAuthenticate = {
    type: 'generic',
    properties: {
      headers: {
        Authorization: '=Bearer {{$credentials.apiKey}}',
      },
    },
  };
  test: ICredentialTestRequest = {
    request: {
      baseURL: 'https://api.example.com',
      url: '/me',
    },
  };
}

Pattern 2: Query String Authentication

authenticate: IAuthenticate = {
  type: 'generic',
  properties: {
    qs: {
      api_key: '={{$credentials.apiKey}}',
    },
  },
};

Pattern 3: Basic Auth

export class MyBasicAuthApi implements ICredentialType {
  name = 'myBasicAuthApi';
  displayName = 'My Basic Auth API';
  properties: INodeProperties[] = [
    {
      displayName: 'Username',
      name: 'username',
      type: 'string',
      default: '',
    },
    {
      displayName: 'Password',
      name: 'password',
      type: 'string',
      typeOptions: { password: true },
      default: '',
    },
  ];
  authenticate: IAuthenticate = {
    type: 'generic',
    properties: {
      auth: {
        username: '={{$credentials.username}}',
        password: '={{$credentials.password}}',
      },
    },
  };
}

Pattern 4: Body Injection

authenticate: IAuthenticate = {
  type: 'generic',
  properties: {
    body: {
      username: '={{$credentials.username}}',
      password: '={{$credentials.password}}',
    },
  },
};

Pattern 5: OAuth2 Credential

import type { ICredentialType, INodeProperties } from 'n8n-workflow';

export class MyServiceOAuth2Api implements ICredentialType {
  name = 'myServiceOAuth2Api';
  displayName = 'My Service OAuth2 API';
  extends = ['oAuth2Api'];
  documentationUrl = 'https://docs.myservice.com/oauth';
  properties: INodeProperties[] = [
    {
      displayName: 'Grant Type',
      name: 'grantType',
      type: 'hidden',
      default: 'authorizationCode',
    },
    {
      displayName: 'Authorization URL',
      name: 'authUrl',
      type: 'hidden',
      default: 'https://myservice.com/oauth/authorize',
    },
    {
      displayName: 'Access Token URL',
      name: 'accessTokenUrl',
      type: 'hidden',
      default: 'https://myservice.com/oauth/token',
    },
    {
      displayName: 'Scope',
      name: 'scope',
      type: 'hidden',
      default: 'read write',
    },
    {
      displayName: 'Auth URI Query Parameters',
      name: 'authQueryParameters',
      type: 'hidden',
      default: '',
    },
    {
      displayName: 'Authentication',
      name: 'authentication',
      type: 'hidden',
      default: 'body',
    },
  ];
}

Pattern 6: Credential Testing

test: ICredentialTestRequest = {
  request: {
    baseURL: '={{$credentials?.baseUrl}}',
    url: '/api/v1/verify',
    method: 'GET',
    skipSslCertificateValidation:
      '={{$credentials?.allowUnauthorizedCerts}}' as unknown as boolean,
  },
};

n8n calls this endpoint when users click "Test" in the credentials dialog. A 2xx response validates the credentials.

Pattern 7: Credential Registration (package.json)

{
  "name": "n8n-nodes-myservice",
  "n8n": {
    "n8nNodesApiVersion": 1,
    "credentials": [
      "dist/credentials/MyServiceApi.credentials.js",
      "dist/credentials/MyServiceOAuth2Api.credentials.js"
    ],
    "nodes": [
      "dist/nodes/MyService/MyService.node.js"
    ]
  }
}

Rule: The n8n.credentials array MUST point to compiled .js files in dist/, NEVER to .ts source files.

Pattern 8: Credential Inheritance (extends)

export class MyServiceApi implements ICredentialType {
  name = 'myServiceApi';
  displayName = 'My Service API';
  extends = ['oAuth2Api'];  // Inherits all OAuth2 properties
  properties: INodeProperties[] = [
    // Only define ADDITIONAL properties here
    // Base OAuth2 properties (clientId, clientSecret, etc.) are inherited
    {
      displayName: 'Region',
      name: 'region',
      type: 'options',
      options: [
        { name: 'US', value: 'us' },
        { name: 'EU', value: 'eu' },
      ],
      default: 'us',
    },
  ];
}

Pattern 9: Using Credentials in Node execute()

async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
  const credentials = await this.getCredentials('exampleApi');
  // credentials.apiKey, credentials.baseUrl, etc.

  const response = await this.helpers.httpRequestWithAuthentication.call(
    this, 'exampleApi', {
      method: 'GET',
      url: `${credentials.baseUrl}/api/data`,
    }
  );

  return [this.helpers.returnJsonArray(response as IDataObject[])];
}

Rule: When using authenticate on the credential, use httpRequestWithAuthentication -- it automatically applies the authenticate configuration. When NOT using authenticate, manually inject credentials into request options.


Credential Node Binding

Link credentials to nodes via the credentials array in INodeTypeDescription:

credentials: [
  {
    name: 'myServiceApi',
    required: true,
  },
  {
    name: 'myServiceOAuth2Api',
    required: true,
    displayOptions: {
      show: { authentication: ['oAuth2'] },
    },
  },
],

Use displayOptions to conditionally show credentials based on an authentication method selector.


Reference Links

Official Sources

Related skills
Installs
1
GitHub Stars
1
First Seen
Apr 3, 2026