Nome da credencial com auto-incremento parece global para credenciais personalizadas, mas por pessoa para alguns built-ins (OpenAI)

{“content”:“Estou vendo um comportamento inconsistente na nomenclatura de credenciais no n8n e quero confirmar se isso é esperado.\n\n### O que observo\n\n* Para meu tipo de credencial personalizado (myApi), novas credenciais são nomeadas automaticamente globalmente em toda a instância:\n\n * Usuário A cria credenciais pessoais: MyApi Account, MyApi Account 2\n\n * Usuário B (que não consegue ver as credenciais pessoais do Usuário A) cria uma e recebe: MyApi Account 3\n\n* Mas por exemplo para credenciais OpenAI, o contador parece ser pessoal/com escopo de projeto (não continua das credenciais de outros usuários da mesma forma).\n\n### Por que isso é confuso\n\nA visibilidade de credenciais é pessoal/baseada em projeto, mas o sufixo de nome gerado para meu tipo personalizado parece usar um contador global. Isso faz com que a nomenclatura pareça “vazar” entre usuários, mesmo que as credenciais não sejam compartilhadas.\n\n### Pergunta\n\n* Essa diferença entre tipos de credenciais integrados (por exemplo, OpenAI) e personalizados é esperada?\n\n* Existem múltiplos fluxos de criação de credenciais/geração de nomes no n8n que explicam isso?\n\n* Há alguma maneira de um tipo de credencial personalizado usar geração de nomes por usuário/por projeto em vez de sufixação global?\n\n\"n8n-workflow\": \"^1.120.13\"”,“target_locale”:“pt_BR”}

Bem vindo à comunidade n8n @Jankaz
você chegou a verificar se a credencial openai está sendo criada pelo mesmo fluxo que a sua credencial customizada (projeto pessoal vs projeto compartilhado vs projeto global do owner)?
Tenho para mim que o seu problema é no caminho interno de criação/nomeação que está sendo usado. consegue compartilhar um repro simples comparando custom credential vs OpenAI credential, incluindo projeto, role do usuário, nomes gerados e comportamento da numeração entre usuários?

Verifiquei as requisições na network e ambas usam https://n8n.stg.olx.org/rest/credentials com a mesma estrutura de payload. Ambas com o mesmo projectId. A única diferença é que o payload do openai tem um campo adicional uiContext: "credentials_list", mas acho que não é o caso

MyApi.credentials.ts

export class MyApi implements ICredentialType {
  name = "myApi";

  displayName = "My API";

  properties: INodeProperties[] = [
    {
      displayName: "URL Base da Plataforma",
      name: "baseUrl",
      type: "string",
      default: "http://myapi.com",
      placeholder: "http://myapi.com",
      required: true,
      hint: "Clique em `Salvar` para autenticar.",
      description: "",
    },
    {
      displayName: "Segredo",
      name: "adminToken",
      type: "hidden",
      typeOptions: {
        password: true,
      },
      default: "",
      description:
        "Preenchido através de substituições de credenciais n8n.",
    },
  ];

  test: ICredentialTestRequest = {
    request: {
      method: "GET",
      baseURL: "={{$credentials.baseUrl}}",
      url: "/health",
    },
  };
}

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

export class OpenAiApi implements ICredentialType {
  name = 'openAiApi';

  displayName = 'OpenAI';

  documentationUrl = 'openai';

  properties: INodeProperties[] = [
   {
    displayName: 'Chave de API',
    name: 'apiKey',
    type: 'string',
    typeOptions: { password: true },
    required: true,
    default: '',
   },
   {
    displayName: 'ID da Organização (opcional)',
    name: 'organizationId',
    type: 'string',
    default: '',
    hint: 'Necessário apenas se você pertencer a várias organizações',
    description:
     "Para usuários que pertencem a várias organizações, você pode definir qual organização é usada para uma solicitação de API. O uso dessas solicitações de API será contabilizado na cota de assinatura da organização especificada.",
   },
   {
    displayName: 'URL Base',
    name: 'url',
    type: 'string',
    default: 'https://api.openai.com/v1',
    description: 'Substitua a URL base padrão para a API',
   },
   {
    displayName: 'Adicionar Cabeçalho Personalizado',
    name: 'header',
    type: 'boolean',
    default: false,
   },
   {
    displayName: 'Nome do Cabeçalho',
    name: 'headerName',
    type: 'string',
    displayOptions: {
     show: {
      header: [true],
     },
    },
    default: '',
   },
   {
    displayName: 'Valor do Cabeçalho',
    name: 'headerValue',
    type: 'string',
    typeOptions: {
     password: true,
    },
    displayOptions: {
     show: {
      header: [true],
     },
    },
    default: '',
   },
  ];

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

  async authenticate(
   credentials: ICredentialDataDecryptedObject,
   requestOptions: IHttpRequestOptions,
  ): Promise<IHttpRequestOptions> {
   requestOptions.headers ??= {};

   requestOptions.headers['Authorization'] = `Bearer ${credentials.apiKey}`;
   requestOptions.headers['OpenAI-Organization'] = credentials.organizationId;

   if (
    credentials.header &&
    typeof credentials.headerName === 'string' &&
    credentials.headerName &&
    typeof credentials.headerValue === 'string'
   ) {
    requestOptions.headers[credentials.headerName] = credentials.headerValue;
   }

   return requestOptions;
  }
}

@Jankaz
Pelo código do backend, parece que o POST /rest/credentials persiste o name recebido no payload, então eu investigaria a geração do nome no frontend antes da requisição ser enviada. Se OpenAI e a credencial customizada chegam ao mesmo endpoint com o mesmo projectId, mas já com nomes diferentes, a diferença provavelmente está no fluxo de UI que calcula o default credential name, não no save() do backend.

Obrigado - concordo que POST `/rest/credential` apenas salva o nome fornecido.
Nos rastreios de rede, tanto a credencial OpenAI quanto a customizada também chamam `GET /rest/credentials/new?name=` antes do POST.
Então a nomeação parece ser determinada por (a) nome base do frontend + (b) geração de nome único no backend em /credentials/new.
Isso sugere que a diferença vem da correspondência de nomes existentes para cada prefixo (OpenAI account% vs GAIP account%), em vez de vir de save() ou uiContext.

Então… qual é a dificuldade em renomear a credencial? :slight_smile:

Estou trabalhando com n8n há cerca de 4 anos, e percebi que deixar o nome base padrão leva a problemas ao atualizar credenciais depois ou ao determinar o que é o quê

não há dificuldade, mas é confuso

é normal @Jankaz , depois que você encontrar a sua forma de entender a questão vai ficar mais fácil. não algo configurável, elas são diferentes visualmente mesmo.

não encontrei nenhum parâmetro para alterar a lógica de geração automática de nomes

A separação por usuário/projeto existe no nível de permissão e visibilidade das credenciais, via RBAC/Projects, mas isso não significa que o contador automático de nomes também seja escopado por projeto. A documentação de RBAC fala sobre acesso a workflows e credenciais por projeto, não sobre algoritmo de nomeação.

como sugerido na thread, o contorno é nomear manualmente as credenciais com projeto/usuário no nome.