Skip to content
Blog

How to Add a Credential Test to an n8n Community Node

A credential test gives n8n a small request it can run when a user saves a credential. For a community node, define the credential class, map the saved fields through authenticate, and add a test.request that reaches a safe provider endpoint. The node can then catch a bad key or wrong host before a workflow operation fails.

The test request should prove authentication with the least data and side effects possible. A read-only account or profile endpoint is usually easier to reason about than a list endpoint that returns thousands of records or an endpoint that changes state.

The NativeShip n8n credentials guide covers the wider API key, OAuth2, and credential setup decisions. This post stays on the implementation boundary: the request n8n uses to test the credential and the checks around it.

When a user clicks Save on a credential, n8n runs this sequence:

  1. Reads the saved field values from the Credentials modal.
  2. Applies your authenticate mapping to build an authenticated request.
  3. Sends test.request to the provider.
  4. Shows "Connection tested successfully" on a 2xx response (and any rules you add pass), or the provider's error otherwise.

Know what the credential test owns

A credential file has separate jobs:

Part Job What to verify
properties Shows fields in the Credentials modal and stores their values Names, types, defaults, required values, and any base URL or tenant field
authenticate Places credential values in the request Header, query string, body, or Basic Auth mapping
test.request Gives n8n a request for checking the saved credential A safe URL, the right base URL, and an endpoint that needs the same authentication
Node credentials array Connects the node to the credential class The exact internal credential name

The test does not prove that every operation works. It checks one authenticated request. Keep operation-specific parameters, response mapping, pagination, and business permissions in their own tests.

Start with the provider's authentication contract

Before writing TypeScript, write down the provider's actual authentication contract. Check its API documentation for the header or query key, the base URL, the required version prefix, and a low-risk endpoint that accepts the credential.

Provider contract authenticate mapping Test concern
API key in a header header Use the exact header spelling and prefix
Bearer token header.Authorization Confirm whether the value includes Bearer
API key in the query string qs Avoid putting secrets in URLs unless the provider requires it
Basic Auth auth with username and password Use an endpoint that supports Basic Auth
Token in the request body body Confirm that the test endpoint accepts the same method and body

The current n8n credentials-file reference documents properties, authenticate, and test. It shows generic authentication mappings for headers, query strings, bodies, and Basic Auth, then places the test URL in test.request.

Do not copy an authentication field from a different service. A credential can look correct in the editor and still fail because the provider expects a different header name, token prefix, host, or API version.

Add the smallest useful credential class

The following is a pattern to adapt to the target API's real authentication contract. The NativeShip custom-node guide covers the surrounding package structure.

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

export class ExampleApi implements ICredentialType {
  name = 'exampleApi';
  displayName = 'Example API';
  documentationUrl = 'https://example.com/docs/auth';

  properties: INodeProperties[] = [
    {
      displayName: 'API key',
      name: 'apiKey',
      type: 'string',
      typeOptions: { password: true },
      default: '',
    },
    {
      displayName: 'Base URL',
      name: 'baseUrl',
      type: 'string',
      default: 'https://api.example.com',
    },
  ];

  authenticate: IAuthenticateGeneric = {
    type: 'generic',
    properties: {
      header: {
        'X-API-Key': '={{$credentials.apiKey}}',
      },
    },
  };

  test: ICredentialTestRequest = {
    request: {
      baseURL: '={{$credentials?.baseUrl}}',
      url: '/v1/account',
    },
  };
}

Mark every secret field with typeOptions: { password: true } so n8n masks it in the editor; the n8n linter flags secret fields without it, and the verified node checklist treats lint as a submission gate. The field names in properties become the names used in the expressions. In this example, authenticate reads apiKey, and test.request reads baseUrl. If the provider has one fixed host, remove the editable base URL and set the documented host in the request or node configuration instead.

Use the actual provider endpoint in place of /v1/account. The endpoint needs to be safe to call repeatedly and should require the same credential that normal node operations use.

Check the response body, not only the status

Some APIs return 200 OK with an error object when a key is wrong. Add rules to the test so n8n inspects the body:

test: ICredentialTestRequest = {
  request: {
    baseURL: '={{$credentials?.baseUrl}}',
    url: '/v1/account',
  },
  rules: [
    {
      type: 'responseSuccessBody',
      properties: {
        key: 'error.code',
        value: 'invalid_api_key',
        message: 'The API key is not valid. Create a new key in your account settings.',
      },
    },
  ],
};

If the value at key matches value, n8n marks the test as failed and shows your message. Write that message for the person in the Credentials modal: say what is wrong and where to fix it.

OAuth2 credentials

For OAuth2, extend n8n's built-in type with extends = ['oAuth2Api'] and set the authorization URL, token URL, and scopes as hidden properties. Connecting the account already runs the token exchange, so an extra test.request is optional. Add one only if a token can be issued while API access is still missing, for example on a plan without API access. The credentials guide compares API key and OAuth2 setups.

Make the test use the same authentication as the node

The test request is only useful when its authentication mapping matches the requests made by the node. If normal operations send X-API-Key, the test should reach an endpoint that accepts that header. If the provider uses a bearer token, include the correct prefix in authenticate and let the test request use that mapping.

Avoid adding a second copy of the secret inside test.request. Keep credential values in authenticate so the same mapping applies to the test and the node's API requests.

Check these details together:

  • Does the field name in the expression match the properties name?
  • Does the auth location match the provider documentation?
  • Does the test endpoint use the same host and API version as the operation?
  • Does the test require a tenant, workspace, or region value that the credential class does not collect?
  • Does the provider reject a token that can call normal endpoints but cannot call the test endpoint?

A credential test can fail because the endpoint needs a permission the normal operation does not need. Choose a test endpoint whose access requirement matches the minimum permission the node promises to support.

Keep the credential name aligned with the node

The credential class's internal name must match the name in the node's credentials array:

credentials: [
  {
    name: 'exampleApi',
    required: true,
  },
],

The n8n credential troubleshooting guide calls out this exact mismatch. If the class uses exampleApi but the node references exampleAPI, n8n cannot resolve the credential type.

Check the same name in every place that registers the credential:

  1. The credential class's name.
  2. The node description's credentials[].name.
  3. The package metadata that registers the node and credential files.
  4. Any testedBy or custom test method name, when the implementation uses one.

A name mismatch is a registration problem. Changing the endpoint will not fix it.

Choose a test endpoint that can explain failure

An endpoint that returns a small account or identity response is useful because it can distinguish authentication from an operation's input requirements. Record the provider's expected response and status behavior before you write error copy.

Result while testing What to inspect next
Success Confirm the returned response does not contain secret values and that the saved credential can run a real read operation
401 or similar authentication failure Check the token value, prefix, header name, and whether the key is expired or revoked
403 or similar permission failure Check scopes, workspace access, and whether the test endpoint needs more permission than the node's first operation
404 Check base URL, version prefix, path, region, and whether the endpoint exists for the account
Timeout or network error Check the host, DNS, TLS, proxy, and self-hosted network path
A valid response with unexpected shape Confirm that the endpoint is the provider's credential-check route, not a normal business response

Treat those rows as debugging directions, not universal n8n status rules. The provider's API contract and the supported n8n version decide how a particular error appears in the editor.

Keep base URLs and paths deliberate

A base URL field helps when the provider has regional or tenant-specific hosts. It also creates another input that the user can mistype. Choose one of these patterns and document it:

  • Fixed host: keep the provider host in the node or credential definition and ask only for the secret.
  • User-supplied host: collect a complete host, validate the value, and use it consistently in test.request and operation requests.
  • Host plus version prefix: decide whether the base URL owns /v1 or each operation owns it. Do not add the prefix in both places.

Test a base URL with and without a trailing slash if the supported n8n request path can receive both forms. Also test a regional host and a wrong host so the editor error points to the real configuration problem.

When the service uses a tenant ID or workspace ID, include that field in the credential only if every request, including the test, needs it. A test that ignores a required tenant field can pass while the first operation fails.

Know when a request object is not enough

The test.request form is a good fit when one authenticated HTTP request can verify the credential. It becomes a poor fit when the provider requires a signed request assembled in code, a token exchange with several calls, a local certificate, or a test decision based on a custom response.

For those cases, add a custom test method in the node and point the credential entry at it with testedBy:

credentials: [{ name: 'exampleApi', required: true, testedBy: 'exampleApiTest' }],

methods = {
  credentialTest: {
    async exampleApiTest(
      this: ICredentialTestFunctions,
      credential: ICredentialsDecrypted,
    ): Promise<INodeCredentialTestResult> {
      try {
        await signAndCallIdentityEndpoint(this, credential.data);
        return { status: 'OK', message: 'Connection successful' };
      } catch (error) {
        return { status: 'Error', message: (error as Error).message };
      }
    },
  },
};

Keep that method small, return a clear success or failure result, and do not broaden it into an operation runner. If you plan to submit for verification, the method must not read environment variables or the file system, and it cannot pull in a runtime dependency for signing. The n8n-node tool documentation explains the current project scaffolding and local development commands; use the same supported version when you test a custom credential path.

Do not switch to a custom test method to hide a wrong endpoint or mismatched credential name. Fix the request and registration contract first.

Test the credential before testing operations

Run the credential test in a local n8n instance with a matrix that separates configuration errors from API behavior:

Test Evidence to record
Valid credential Test response, n8n version, package version, and endpoint
Invalid or revoked secret Error status and safe editor message
Missing required field Credential form validation and test result
Wrong base URL or version Resolved request and provider response
Insufficient permission Scope or workspace setting and returned status
Regional or tenant host Host value, request path, and result
Credential name mismatch Registration error before changing the endpoint
First real read operation Operation request, response shape, and whether the same credential works
Secret in an error or log Confirm it is redacted before sharing evidence

Start the instance with npm run dev. From n8n 3.0, n8n-node dev runs n8n in a container, so install Docker or Podman, or run n8n-node dev --external-n8n against your own instance started with N8N_DEV_RELOAD=true. Use the NativeShip custom-node debugging guide to inspect the resolved request and registration path when a local test fails. Keep API keys, bearer tokens, cookies, and private response data out of screenshots and logs.

Once it passes, explain the credential setup in your README (where to find the key, which plan or scope it needs); the README checklist shows what to include. A passing credential test is one gate in node development. It gives the editor a reliable check for the saved authentication details, while each operation still needs its own request, permission, response, and error test.

Frequently asked questions

It gives n8n a request to run when the user saves the credential, to check that the saved values can authenticate with the provider. The request goes in test.request, and optional rules let n8n flag a 200 response whose body still reports an error.

authenticate tells n8n where to place credential values on a request. test.request tells n8n which URL to call for the credential check.

No. It checks one authenticated request. Each operation still needs tests for its parameters, permissions, response shape, pagination, and provider errors.

Use a small, read-only endpoint that requires the same authentication and minimum permission as the node. Account or identity endpoints are common choices when the provider documents them.

The credential class name and the node's credentials array name do not match, or the package did not register the credential file. Check the internal name in every registration point.

Use one when a single request object cannot represent the provider's signing, token exchange, certificate, or multi-request flow. Add a credentialTest method to the node, reference it with testedBy in the credentials array, and return { status: 'OK' } or { status: 'Error', message }.

Run the test in a controlled local instance, redact keys and tokens from screenshots and logs, and record the endpoint, version, status, and safe error message instead of the credential value.

Ready to launch your n8n, Make, Zapier or Activepieces integration?

Give your customers another way to use your product.

Get started