diff --git a/packages/cli/package.json b/packages/cli/package.json index c57822ec70..f7a85bed09 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -90,10 +90,6 @@ "ts-essentials": "^7.0.3" }, "dependencies": { - "@langchain/community": "0.2.2", - "@langchain/core": "0.2.9", - "@langchain/openai": "0.0.33", - "@langchain/pinecone": "0.0.6", "@n8n/client-oauth2": "workspace:*", "@n8n/localtunnel": "2.1.0", "@n8n/n8n-nodes-langchain": "workspace:*", @@ -101,7 +97,6 @@ "@n8n/typeorm": "0.3.20-10", "@n8n_io/license-sdk": "2.13.0", "@oclif/core": "4.0.7", - "@pinecone-database/pinecone": "2.1.0", "@rudderstack/rudder-sdk-node": "2.0.7", "@sentry/integrations": "7.87.0", "@sentry/node": "7.87.0", @@ -130,7 +125,6 @@ "fast-glob": "3.2.12", "flatted": "3.2.7", "formidable": "3.5.1", - "fuse.js": "^7.0.0", "google-timezones-json": "1.1.0", "handlebars": "4.7.8", "helmet": "7.1.0", @@ -141,7 +135,6 @@ "json-diff": "1.0.6", "jsonschema": "1.4.1", "jsonwebtoken": "9.0.2", - "langchain": "0.2.2", "ldapts": "4.2.6", "lodash": "4.17.21", "luxon": "3.3.0", @@ -185,7 +178,6 @@ "xml2js": "0.6.2", "xmllint-wasm": "3.0.1", "yamljs": "0.3.0", - "zod": "3.22.4", - "zod-to-json-schema": "3.22.4" + "zod": "3.22.4" } } diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 133be8c8aa..04496e4c8a 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -37,9 +37,9 @@ import { InternalHooks } from '@/InternalHooks'; import { handleMfaDisable, isMfaFeatureEnabled } from '@/Mfa/helpers'; import type { FrontendService } from '@/services/frontend.service'; import { OrchestrationService } from '@/services/orchestration.service'; +import { AuditEventRelay } from './eventbus/audit-event-relay.service'; import '@/controllers/activeWorkflows.controller'; -import '@/controllers/ai.controller'; import '@/controllers/auth.controller'; import '@/controllers/binaryData.controller'; import '@/controllers/curl.controller'; @@ -66,7 +66,6 @@ import '@/ExternalSecrets/ExternalSecrets.controller.ee'; import '@/license/license.controller'; import '@/workflows/workflowHistory/workflowHistory.controller.ee'; import '@/workflows/workflows.controller'; -import { AuditEventRelay } from './eventbus/audit-event-relay.service'; const exec = promisify(callbackExec); diff --git a/packages/cli/src/config/schema.ts b/packages/cli/src/config/schema.ts index 46489dac96..0b48753001 100644 --- a/packages/cli/src/config/schema.ts +++ b/packages/cli/src/config/schema.ts @@ -1380,34 +1380,6 @@ export const schema = { default: false, env: 'N8N_AI_ENABLED', }, - provider: { - doc: 'AI provider to use. Currently only "openai" is supported.', - format: String, - default: 'openai', - env: 'N8N_AI_PROVIDER', - }, - openAI: { - apiKey: { - doc: 'Enable AI features using OpenAI API key', - format: String, - default: '', - env: 'N8N_AI_OPENAI_API_KEY', - }, - model: { - doc: 'OpenAI model to use', - format: String, - default: 'gpt-4-turbo', - env: 'N8N_AI_OPENAI_MODEL', - }, - }, - pinecone: { - apiKey: { - doc: 'Enable AI features using Pinecone API key', - format: String, - default: '', - env: 'N8N_AI_PINECONE_API_KEY', - }, - }, }, expression: { diff --git a/packages/cli/src/constants.ts b/packages/cli/src/constants.ts index 7c1e7f69c5..28b27d1b38 100644 --- a/packages/cli/src/constants.ts +++ b/packages/cli/src/constants.ts @@ -148,8 +148,6 @@ export const TEST_WEBHOOK_TIMEOUT = 2 * TIME.MINUTE; export const TEST_WEBHOOK_TIMEOUT_BUFFER = 30 * TIME.SECOND; -export const N8N_DOCS_URL = 'https://docs.n8n.io'; - export const GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE = [ 'oAuth2Api', 'googleOAuth2Api', diff --git a/packages/cli/src/controllers/ai.controller.ts b/packages/cli/src/controllers/ai.controller.ts deleted file mode 100644 index c22e8a524b..0000000000 --- a/packages/cli/src/controllers/ai.controller.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Post, RestController } from '@/decorators'; -import { AIRequest } from '@/requests'; -import { AIService } from '@/services/ai.service'; -import { FailedDependencyError } from '@/errors/response-errors/failed-dependency.error'; - -@RestController('/ai') -export class AIController { - constructor(private readonly aiService: AIService) {} - - /** - * Generate CURL request and additional HTTP Node metadata for given service and request - */ - @Post('/generate-curl') - async generateCurl(req: AIRequest.GenerateCurl): Promise<{ curl: string; metadata?: object }> { - const { service, request } = req.body; - - try { - return await this.aiService.generateCurl(service, request); - } catch (aiServiceError) { - throw new FailedDependencyError( - (aiServiceError as Error).message || - 'Failed to generate HTTP Request Node parameters due to an issue with an external dependency. Please try again later.', - ); - } - } -} diff --git a/packages/cli/src/errors/response-errors/failed-dependency.error.ts b/packages/cli/src/errors/response-errors/failed-dependency.error.ts deleted file mode 100644 index 243de02665..0000000000 --- a/packages/cli/src/errors/response-errors/failed-dependency.error.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ResponseError } from './abstract/response.error'; - -export class FailedDependencyError extends ResponseError { - constructor(message: string, errorCode = 424) { - super(message, 424, errorCode); - } -} diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index 8363968815..1ff6537257 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -169,19 +169,6 @@ export function hasSharing( return workflows.some((w) => 'shared' in w); } -// ---------------------------------- -// /ai -// ---------------------------------- - -export declare namespace AIRequest { - export type GenerateCurl = AuthenticatedRequest<{}, {}, AIGenerateCurlPayload>; -} - -export interface AIGenerateCurlPayload { - service: string; - request: string; -} - // ---------------------------------- // /credentials // ---------------------------------- diff --git a/packages/cli/src/services/ai.service.ts b/packages/cli/src/services/ai.service.ts deleted file mode 100644 index b2720d7cc6..0000000000 --- a/packages/cli/src/services/ai.service.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { Service } from 'typedi'; -import config from '@/config'; -import type { N8nAIProviderType } from 'n8n-workflow'; -import { ApplicationError, jsonParse } from 'n8n-workflow'; -import type { BaseMessageLike } from '@langchain/core/messages'; -import { AIProviderOpenAI } from '@/services/ai/providers/openai'; -import type { BaseChatModelCallOptions } from '@langchain/core/language_models/chat_models'; -import { Pinecone } from '@pinecone-database/pinecone'; -import type { z } from 'zod'; -import apiKnowledgebase from '@/services/ai/resources/api-knowledgebase.json'; -import { JsonOutputFunctionsParser } from 'langchain/output_parsers'; -import { - generateCurlCommandFallbackPromptTemplate, - generateCurlCommandPromptTemplate, -} from '@/services/ai/prompts/generateCurl'; -import { generateCurlSchema } from '@/services/ai/schemas/generateCurl'; -import { PineconeStore } from '@langchain/pinecone'; -import Fuse from 'fuse.js'; -interface APIKnowledgebaseService { - id: string; - title: string; - description?: string; -} - -function isN8nAIProviderType(value: string): value is N8nAIProviderType { - return ['openai'].includes(value); -} - -@Service() -export class AIService { - private providerType: N8nAIProviderType = 'unknown'; - - public provider: AIProviderOpenAI; - - public pinecone: Pinecone; - - private jsonOutputParser = new JsonOutputFunctionsParser(); - - constructor() { - const providerName = config.getEnv('ai.provider'); - - if (isN8nAIProviderType(providerName)) { - this.providerType = providerName; - } - - if (this.providerType === 'openai') { - const openAIApiKey = config.getEnv('ai.openAI.apiKey'); - const openAIModelName = config.getEnv('ai.openAI.model'); - - if (openAIApiKey) { - this.provider = new AIProviderOpenAI({ openAIApiKey, modelName: openAIModelName }); - } - } - - const pineconeApiKey = config.getEnv('ai.pinecone.apiKey'); - if (pineconeApiKey) { - this.pinecone = new Pinecone({ - apiKey: pineconeApiKey, - }); - } - } - - async prompt(messages: BaseMessageLike[], options?: BaseChatModelCallOptions) { - if (!this.provider) { - throw new ApplicationError('No AI provider has been configured.'); - } - - return await this.provider.invoke(messages, options); - } - - validateCurl(result: { curl: string }) { - if (!result.curl.startsWith('curl')) { - throw new ApplicationError( - 'The generated HTTP Request Node parameters format is incorrect. Please adjust your request and try again.', - ); - } - - result.curl = result.curl - /* - * Replaces placeholders like `{VALUE}` or `{{VALUE}}` with quoted placeholders `"{VALUE}"` or `"{{VALUE}}"`, - * ensuring that the placeholders are properly formatted within the curl command. - * - ": a colon followed by a double quote and a space - * - ( starts a capturing group - * - \{\{ two opening curly braces - * - [A-Za-z0-9_]+ one or more alphanumeric characters or underscores - * - }} two closing curly braces - * - | OR - * - \{ an opening curly brace - * - [A-Za-z0-9_]+ one or more alphanumeric characters or underscores - * - } a closing curly brace - * - ) ends the capturing group - * - /g performs a global search and replace - * - */ - .replace(/": (\{\{[A-Za-z0-9_]+}}|\{[A-Za-z0-9_]+})/g, '": "$1"') // Fix for placeholders `curl -d '{ "key": {VALUE} }'` - /* - * Removes the rogue curly bracket at the end of the curl command if it is present. - * It ensures that the curl command is properly formatted and doesn't have an extra closing curly bracket. - * - ( starts a capturing group - * - -d flag in the curl command - * - ' a single quote - * - [^']+ one or more characters that are not a single quote - * - ' a single quote - * - ) ends the capturing group - * - } a closing curly bracket - */ - .replace(/(-d '[^']+')}/, '$1'); // Fix for rogue curly bracket `curl -d '{ "key": "value" }'}` - - return result; - } - - async generateCurl(serviceName: string, serviceRequest: string) { - this.checkRequirements(); - - if (!this.pinecone) { - return await this.generateCurlGeneric(serviceName, serviceRequest); - } - - const fuse = new Fuse(apiKnowledgebase as unknown as APIKnowledgebaseService[], { - threshold: 0.25, - useExtendedSearch: true, - keys: ['id', 'title'], - }); - - const matchedServices = fuse - .search(serviceName.replace(/ +/g, '|')) - .map((result) => result.item); - - if (matchedServices.length === 0) { - return await this.generateCurlGeneric(serviceName, serviceRequest); - } - - const pcIndex = this.pinecone.Index('api-knowledgebase'); - const vectorStore = await PineconeStore.fromExistingIndex(this.provider.embeddings, { - namespace: 'endpoints', - pineconeIndex: pcIndex, - }); - - const matchedDocuments = await vectorStore.similaritySearch( - `${serviceName} ${serviceRequest}`, - 4, - { - id: { - $in: matchedServices.map((service) => service.id), - }, - }, - ); - - if (matchedDocuments.length === 0) { - return await this.generateCurlGeneric(serviceName, serviceRequest); - } - - const aggregatedDocuments = matchedDocuments.reduce((acc, document) => { - const pageData = jsonParse(document.pageContent); - - acc.push(pageData); - - return acc; - }, []); - - const generateCurlChain = generateCurlCommandPromptTemplate - .pipe(this.provider.modelWithOutputParser(generateCurlSchema)) - .pipe(this.jsonOutputParser); - const result = (await generateCurlChain.invoke({ - endpoints: JSON.stringify(aggregatedDocuments), - serviceName, - serviceRequest, - })) as z.infer; - - return this.validateCurl(result); - } - - async generateCurlGeneric(serviceName: string, serviceRequest: string) { - this.checkRequirements(); - - const generateCurlFallbackChain = generateCurlCommandFallbackPromptTemplate - .pipe(this.provider.modelWithOutputParser(generateCurlSchema)) - .pipe(this.jsonOutputParser); - const result = (await generateCurlFallbackChain.invoke({ - serviceName, - serviceRequest, - })) as z.infer; - - return this.validateCurl(result); - } - - checkRequirements() { - if (!this.provider) { - throw new ApplicationError('No AI provider has been configured.'); - } - } -} diff --git a/packages/cli/src/services/ai/prompts/generateCurl.ts b/packages/cli/src/services/ai/prompts/generateCurl.ts deleted file mode 100644 index 6c1dda57c6..0000000000 --- a/packages/cli/src/services/ai/prompts/generateCurl.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - ChatPromptTemplate, - HumanMessagePromptTemplate, - SystemMessagePromptTemplate, -} from '@langchain/core/prompts'; - -export const generateCurlCommandPromptTemplate = new ChatPromptTemplate({ - promptMessages: [ - SystemMessagePromptTemplate.fromTemplate(`# What you need to do - -You are a curl command generator engine. Your task is to provide a curl command that the user could run to call the endpoint they described. - -When generating the curl data, make sure it's a 100% valid stringified JSON format. - -Use placeholders with the \`{{PLACEHOLDER}}\` format for the parameters that need to be filled with real-world example values. - -# What you need to know - -Here is the specification for an API you will be working with: - -\`\`\`json -{endpoints} -\`\`\` - -# How to complete the task - -To do this, take your time to analyze the API specification entries and then follow these steps: - -1. Carefully read the user's prompt to determine which specific API endpoint and HTTP method (GET, POST, etc.) they need to use. -2. List out the required parameters needed to make a successful request to that endpoint. Parameters can be included in the url, query string, headers, or request body. -3. Include the correct authentication mechanism to make a successful request to that endpoint. Ensure the curl command includes all the necessary headers and authentication information. -4. Outline the structure of the curl command, including the HTTP method, full URL, and all the required parameters. -5. Write out the final curl command that the user could copy and paste to execute the API request they described. - -IMPORTANT: Only construct a curl command for the specific endpoint and method that matches what the user described. Ensure that the command is valid and respects the steps above. If you fail to provide a valid curl command, your response will be rejected.`), - HumanMessagePromptTemplate.fromTemplate(`Service name: {serviceName} -Service request: {serviceRequest}`), - ], - inputVariables: ['endpoints', 'serviceName', 'serviceRequest'], -}); - -export const generateCurlCommandFallbackPromptTemplate = new ChatPromptTemplate({ - promptMessages: [ - SystemMessagePromptTemplate.fromTemplate(`# What you need to do - -You are a curl command generator engine. Your task is to provide a curl command that the user could run to call the endpoint they described. - -When generating the curl data, make sure it's a 100% valid stringified JSON format. - -Use placeholders with the \`{{PLACEHOLDER}}\` format for the parameters that need to be filled with real-world example values. - -# How to complete the task - -To construct the curl command, follow these steps: - -1. Carefully read the user's prompt to determine which specific API the user will interact with based on the provided service name and description. List out the HTTP method (GET, POST, etc.), full endpoint URL, and all the required parameters, including the \`url\`, \`method\`, \`headers\`, \`query\`, \`body\`, and authentication mechanism. -2. List out the required parameters needed to make a successful request to that endpoint. Parameters can be included in the url, query string, headers, or request body. -3. Include the correct authentication mechanism to make a successful request to that endpoint. Ensure the curl command includes all the necessary headers and authentication information. If you are unsure about the authentication mechanism, you can infer the most likely authentication method based on the API specification. -4. Outline the structure of the curl command, including the HTTP method, full URL, and all the required parameters. Fill the required parameters with real-world example values. -5. Write out the final curl command that the user could copy and paste to execute the API request they described. - -IMPORTANT: Only construct a curl command for the specific endpoint and method that matches what the user described. Ensure that the command is valid and respects the steps above. If you fail to provide a valid curl command, your response will be rejected.`), - HumanMessagePromptTemplate.fromTemplate(`Service name: {serviceName} -Service request: {serviceRequest}`), - ], - inputVariables: ['serviceName', 'serviceRequest'], -}); diff --git a/packages/cli/src/services/ai/prompts/retrieveService.ts b/packages/cli/src/services/ai/prompts/retrieveService.ts deleted file mode 100644 index b47c73ef05..0000000000 --- a/packages/cli/src/services/ai/prompts/retrieveService.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { - ChatPromptTemplate, - HumanMessagePromptTemplate, - SystemMessagePromptTemplate, -} from '@langchain/core/prompts'; - -export const retrieveServicePromptTemplate = new ChatPromptTemplate({ - promptMessages: [ - SystemMessagePromptTemplate.fromTemplate(`Based on the list of available service APIs in the CSV, please return the \`id\` of the CSV entry that is most relevant for the user provided request. - -List Available service APIs in the following CSV Format: \`id\` | \`title\` | \`description\` -\`\`\`csv -{services} -\`\`\` - -IMPORTANT: Return the \`id\` of the service exactly as found in the CSV. If none of the services match perfectly, always return the \`id\` as empty string, NEVER hallucinate a service that is not on this list.`), - HumanMessagePromptTemplate.fromTemplate(`Service API name: {serviceName} -Service API Request: {serviceRequest}`), - ], - inputVariables: ['services', 'serviceName', 'serviceRequest'], -}); diff --git a/packages/cli/src/services/ai/providers/openai.ts b/packages/cli/src/services/ai/providers/openai.ts deleted file mode 100644 index 81e699b507..0000000000 --- a/packages/cli/src/services/ai/providers/openai.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai'; -import type { BaseMessageChunk, BaseMessageLike } from '@langchain/core/messages'; -import type { N8nAIProvider } from '@/types/ai.types'; -import type { BaseChatModelCallOptions } from '@langchain/core/language_models/chat_models'; -import { zodToJsonSchema } from 'zod-to-json-schema'; -import type { ZodSchema } from 'zod'; - -export class AIProviderOpenAI implements N8nAIProvider { - public model: ChatOpenAI; - - public embeddings: OpenAIEmbeddings; - - constructor({ openAIApiKey, modelName }: { openAIApiKey: string; modelName: string }) { - this.model = new ChatOpenAI({ - openAIApiKey, - modelName, - timeout: 60000, - maxRetries: 2, - temperature: 0, - }); - - this.embeddings = new OpenAIEmbeddings({ - openAIApiKey, - modelName: 'text-embedding-3-small', - }); - } - - modelWithOutputParser(schema: T) { - return this.model.bind({ - functions: [ - { - name: 'output_formatter', - description: 'Should always be used to properly format output', - parameters: zodToJsonSchema(schema), - }, - ], - function_call: { - name: 'output_formatter', - }, - }); - } - - mapResponse(data: BaseMessageChunk): string { - if (Array.isArray(data.content)) { - return data.content - .map((message): string => - 'text' in message - ? (message.text as string) - : 'image_url' in message - ? (message.image_url as string) - : '', - ) - .join('\n'); - } - - return data.content; - } - - async invoke(messages: BaseMessageLike[], options?: BaseChatModelCallOptions) { - const data = await this.model.invoke(messages, options); - - return this.mapResponse(data); - } -} diff --git a/packages/cli/src/services/ai/resources/README.md b/packages/cli/src/services/ai/resources/README.md deleted file mode 100644 index d911864b4e..0000000000 --- a/packages/cli/src/services/ai/resources/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# AI Resources - -## API Knowledgebase - -**File**: `api-knowledgebase.json` - -The relevant repository for generating this file is [here](https://github.com/n8n-io/n8n-ai-apis-knowledgebase). - -This file is **auto-generated** for the AI Service, and it contains a list of all the available APIs that can be used to train the AI model from our Vector Store. Currently, this is used when generating a `curl` command for the HTTP Request Node. diff --git a/packages/cli/src/services/ai/resources/api-knowledgebase.json b/packages/cli/src/services/ai/resources/api-knowledgebase.json deleted file mode 100644 index 2f22e56e64..0000000000 --- a/packages/cli/src/services/ai/resources/api-knowledgebase.json +++ /dev/null @@ -1,2651 +0,0 @@ -[ - { - "title": "Pipedrive", - "id": "pipedrive.com" - }, - { - "title": "OpenAI", - "id": "openai.com" - }, - { - "title": "Discourse", - "id": "discourse.com" - }, - { - "title": "Anthropic Claude", - "id": "anthropic.com" - }, - { - "title": "Zoho CRM", - "id": "zoho.com-crm" - }, - { - "title": "Notion", - "id": "notion.so" - }, - { - "title": "Stripe", - "id": "stripe.com" - }, - { - "title": "DocuSign", - "id": "docusign.com" - }, - { - "title": "Plaid", - "id": "plaid.com" - }, - { - "title": "Zendesk Support", - "id": "zendesk.com-support" - }, - { - "title": "Salesforce Marketing Cloud", - "id": "salesforce.com-marketing-cloud" - }, - { - "title": "Spoonacular", - "id": "spoonacular.com" - }, - { - "title": "Datadog", - "id": "datadoghq.com" - }, - { - "title": "WeChatPay", - "id": "wechat.com-pay", - "version": "v3" - }, - { - "title": "ActiveCampaign", - "id": "activecampaign.com", - "version": "v3" - }, - { - "title": "Feishu", - "id": "feishu.cn" - }, - { - "title": "Whatsapp Business Management", - "id": "whatsapp.com-business-management" - }, - { - "title": "Brevo", - "id": "brevo.com" - }, - { - "title": "Salesforce Data Cloud", - "id": "salesforce.com-data-cloud" - }, - { - "title": "Xendit", - "id": "xendit.co" - }, - { - "title": "Amadeus for Developers", - "id": "amadeus.com-developers" - }, - { - "title": "Pynt", - "id": "pynt.io" - }, - { - "title": "ClickUp", - "id": "clickup.com" - }, - { - "title": "Twilio Messaging / SMS", - "id": "twilio.com-messaging" - }, - { - "title": "Amplitude Analytics", - "id": "amplitude.com-analytics" - }, - { - "title": "Box Platform", - "id": "box.com-platform" - }, - { - "title": "HotelBeds Booking", - "id": "hotelbeds.com-booking" - }, - { - "title": "Monday.com", - "id": "monday.com" - }, - { - "title": "Zoom", - "id": "zoom.com" - }, - { - "title": "Zendesk Help Center", - "id": "zendesk.com-help-center" - }, - { - "title": "GigaChat", - "id": "gigachat.app" - }, - { - "title": "Shiprocket", - "id": "shiprocket.in" - }, - { - "title": "Whatsapp On-Premises", - "id": "whatsapp.com-on-premises" - }, - { - "title": "Customer.io Journeys Track", - "id": "customer.io-journeys-track" - }, - { - "title": "Sportmonks", - "id": "sportmonks.com", - "version": "3" - }, - { - "title": "Power BI", - "id": "microsoft.com-power-bi", - "version": "v1" - }, - { - "title": "Flutterwave", - "id": "flutterwave.com", - "version": "3.0" - }, - { - "title": "HotelBeds Content", - "id": "hotelbeds.com-content" - }, - { - "title": "Salesforce Tableau", - "id": "salesforce.com-tableau" - }, - { - "title": "Cashfree Payment Gateway", - "id": "cashfree.com-payment-gateway" - }, - { - "title": "Belvo Docs", - "id": "belvo.com" - }, - { - "title": "Discord", - "id": "discord.com" - }, - { - "title": "Zoom Meeting", - "id": "zoom.com-meeting" - }, - { - "title": "Salesforce Marketing Cloud Account Engagement (Pardot)", - "id": "salesforce.com-marketing-cloud-account-engagement", - "version": "v5" - }, - { - "title": "Cloudinary Upload", - "id": "cloudinary.com-upload" - }, - { - "title": "PingOne Platform", - "id": "pingone.com" - }, - { - "title": "SEON", - "id": "seon.io" - }, - { - "title": "Eden AI", - "id": "edenai.io" - }, - { - "title": "Fireblocks", - "id": "fireblocks.com" - }, - { - "title": "PagerDuty", - "id": "pagerduty.com" - }, - { - "title": "WooCommerce", - "id": "woocommerce.com" - }, - { - "title": "DocuSign Admin", - "id": "docusign.com-admin" - }, - { - "title": "Google Books", - "id": "google.com-books" - }, - { - "title": "CountriesNow Countries & Cities", - "id": "countriesnow.space" - }, - { - "title": "Aadhaar KYC", - "id": "aadhaarkyc.io" - }, - { - "title": "Zendesk Chat", - "id": "zendesk.com-chat" - }, - { - "title": "Cloudflare R2", - "id": "cloudflare.com-r2" - }, - { - "title": "ScrapingBee", - "id": "scrapingbee.com" - }, - { - "title": "UiPath Add-ins", - "id": "uipath.com-add-ins" - }, - { - "title": "Instagram", - "id": "instagram.com" - }, - { - "title": "PandaDoc", - "id": "pandadoc.com" - }, - { - "title": "CyberArk", - "id": "cyberark.com" - }, - { - "title": "100ms", - "id": "100ms.live" - }, - { - "title": "Shopify", - "id": "shopify.com" - }, - { - "title": "Salesforce Commerce B2C", - "id": "salesforce.com-commerce-b2c" - }, - { - "title": "Adyen Checkout", - "id": "adyen.com-checkout", - "version": "v71" - }, - { - "title": "DoorDash Drive", - "id": "doordash.com-drive" - }, - { - "title": "Airwallex", - "id": "airwallex.com" - }, - { - "title": "Snowflake SQL", - "id": "snowflake.com-sql", - "version": "v2" - }, - { - "title": "Twitter Developer Labs", - "id": "twitter.com-developer-labs" - }, - { - "title": "Hyperledger Besu JSON-RPC", - "id": "hyperledger.org-besu" - }, - { - "title": "Plivo", - "id": "plivo.com" - }, - { - "title": "Facebook", - "id": "facebook.com" - }, - { - "title": "LinkedIn Content", - "id": "linkedin.com-content" - }, - { - "title": "Jira", - "id": "atlassian.com-jira" - }, - { - "title": "OneSignal", - "id": "onesignal.com" - }, - { - "title": "Immoscout24 OAuth1", - "id": "immoscout24.com-oauth" - }, - { - "title": "DocuSign eSignature", - "id": "docusign.com-esignature" - }, - { - "title": "Snowflake", - "id": "snowflake.com" - }, - { - "title": "Cloudinary Admin", - "id": "cloudinary.com-admin" - }, - { - "title": "Viva Payments", - "id": "viva.com-create-payment-order", - "version": "v2" - }, - { - "title": "SportRadar", - "id": "sportradar.com" - }, - { - "title": "Contentstack Content Delivery", - "id": "contentstack.io-content-delivery" - }, - { - "title": "TikTok Business", - "id": "tiktok.com-business", - "version": "v1.3" - }, - { - "title": "F1 Formula One", - "id": "f1.com" - }, - { - "title": "TMDB The Movie Database", - "id": "themoviedb.org" - }, - { - "title": "Wordpress", - "id": "wordpress.com", - "version": "v2" - }, - { - "title": "SBER SaluteSpeech", - "id": "sber.ru" - }, - { - "title": "Symbl AI", - "id": "symbl.ai" - }, - { - "title": "Onfido", - "id": "onfido.com", - "version": "v3.6" - }, - { - "title": "Binance Perpetual Future", - "id": "binance.com-futures" - }, - { - "title": "Reloadly", - "id": "reloadly.com" - }, - { - "title": "Nylas", - "id": "nylas.com", - "version": "v2" - }, - { - "title": "Mist Cloud", - "id": "juniper.net-mist", - "version": "2402.1.0" - }, - { - "title": "LinkedIn Campaign Management", - "id": "linkedin.com-campaign-management" - }, - { - "title": "Shutterstock", - "id": "shutterstock.com" - }, - { - "title": "OpenWeatherMap", - "id": "openweathermap.org" - }, - { - "title": "Whatsapp Embedded Signup", - "id": "whatsapp.com-embedded-signup" - }, - { - "title": "SailPoint IdentityNow", - "id": "sailpoint.com", - "version": "v3" - }, - { - "title": "ChatBot.com", - "id": "chatbot.com" - }, - { - "title": "Lob", - "id": "lob.com" - }, - { - "title": "Binance Spot", - "id": "binance.com-spot" - }, - { - "title": "MoMo E-Wallet Payments", - "id": "momo.com" - }, - { - "title": "Mailosaur", - "id": "mailosaur.com" - }, - { - "title": "Rasa Open Source HTTP", - "id": "rasa.com" - }, - { - "title": "DingConnect", - "id": "dingconnect.com" - }, - { - "title": "Withings Health Solutions", - "id": "withings.com" - }, - { - "title": "Solid FinTech Platform", - "id": "solidfintech.com" - }, - { - "title": "Chatwoot", - "id": "chatwoot.com", - "version": "v1.0" - }, - { - "title": "Kontent.ai", - "id": "kontent.ai" - }, - { - "title": "Gmail", - "id": "google.com-gmail" - }, - { - "title": "PayBoxMoney PaymentPage", - "id": "payboxmoney.com" - }, - { - "title": "Dropbox", - "id": "dropbox.com" - }, - { - "title": "Quotable", - "id": "quotable.io" - }, - { - "title": "ShipEngine", - "id": "shipengine.com" - }, - { - "title": "Alpaca Market Data", - "id": "alpaca.markets", - "version": "v2" - }, - { - "title": "Twitter Premium", - "id": "twitter.com-premium" - }, - { - "title": "Livechat Authorization", - "id": "livechat.com-authorization" - }, - { - "title": "NASA - Astronomy Picture of the Day (APOD)", - "id": "nasa.gov-apod" - }, - { - "title": "Bridge", - "id": "bridgeapi.io", - "version": "v2021.06.01" - }, - { - "title": "Contentstack Content Management", - "id": "contentstack.io-content-management" - }, - { - "title": "SportRadar Soccer", - "id": "sportradar.com-soccer", - "version": "v4" - }, - { - "title": "VIVA Payments OAuth2 Authentication", - "id": "viva.com-oauth" - }, - { - "title": "Infura Ethereum JSON-RPC", - "id": "infura.io" - }, - { - "title": "Box Dev Platform", - "id": "box.com" - }, - { - "title": "Zomato", - "id": "zomato.com" - }, - { - "title": "Temenos", - "id": "temenos.com" - }, - { - "title": "Yousign", - "id": "yousign.com", - "version": "v3" - }, - { - "title": "SportRadar NBA", - "id": "sportradar.com-nba", - "version": "v8" - }, - { - "title": "MuleSoft Anypoint Platform", - "id": "mulesoft.com" - }, - { - "title": "YouTube", - "id": "youtube.com" - }, - { - "title": "Duffel", - "id": "duffel.com" - }, - { - "title": "Sendbird Chat", - "id": "sendbird.com" - }, - { - "title": "Checkr.com", - "id": "checkr.com" - }, - { - "title": "LinkedIn Community Management", - "id": "linkedin.com-community-management" - }, - { - "title": "Alpaca Broker", - "id": "alpaca.markets-broker" - }, - { - "title": "Twilio", - "id": "twilio.com" - }, - { - "title": "Akamai Application Security", - "id": "akamai.com-application-security" - }, - { - "title": "ArcGIS Geocoding & Search (Geolocation)", - "id": "arcgis.com-geolocation" - }, - { - "title": "Mux", - "id": "mux.com" - }, - { - "title": "Change Healthcare Medical Network Eligibility", - "id": "changehealthcare.com-eligibility", - "version": "v3" - }, - { - "title": "Mangopay", - "id": "mangopay.com" - }, - { - "title": "Amazon Selling Partner for Orders", - "id": "amazon.com-selling-partner-orders" - }, - { - "title": "Aisensy Campaign", - "id": "aisensy.com" - }, - { - "title": "Akamai Property Manager", - "id": "akamai.com-property-manager" - }, - { - "title": "Sendcloud", - "id": "sendcloud.com" - }, - { - "title": "Viva Payments Request Access Token", - "id": "viva.com-request-access-token" - }, - { - "title": "Akamai Fast Purge", - "id": "akamai.com-fast-purge", - "version": "v3" - }, - { - "title": "Atlassian Confluence Cloud", - "id": "atlassian.com-confluence" - }, - { - "title": "Azure Active Directory Protocols", - "id": "microsoft.com-aad", - "version": "v2.0" - }, - { - "title": "LinkedIn Live Events", - "id": "linkedin.com-live-events" - }, - { - "title": "Strava", - "id": "strava.com", - "version": "v3" - }, - { - "title": "Creatio", - "id": "creatio.com" - }, - { - "title": "WhatsApp Flows", - "id": "whatsapp.com-flows" - }, - { - "title": "Docker HUB", - "id": "docker.com" - }, - { - "title": "LinkedIn Reporting & ROI", - "id": "linkedin.com-reporting" - }, - { - "title": "Xero Accounting", - "id": "xero.com-accounting" - }, - { - "title": "Vonage Contact Center", - "id": "vonage.com" - }, - { - "title": "AWS Amazon Web Services S3", - "id": "aws.com-s3" - }, - { - "title": "Google Analytics", - "id": "google.com-analytics" - }, - { - "title": "NFTPort", - "id": "nftport.com" - }, - { - "title": "JVLcart - MERN Ecommerce", - "id": "jvlcart.com" - }, - { - "title": "SendGrid", - "id": "sendgrid.com" - }, - { - "title": "YouTrack", - "id": "youtrack.com" - }, - { - "title": "USPS Web Tools Address Validation", - "id": "usps.com" - }, - { - "title": "Strapi", - "id": "strapi.io" - }, - { - "title": "MicroStrategy", - "id": "microstrategy.com" - }, - { - "title": "Cisco IOS-XE", - "id": "cisco.com-ios-xe" - }, - { - "title": "Proxycurl", - "id": "proxycurl.com" - }, - { - "title": "Salesforce Commerce B2B/D2C", - "id": "salesforce.com-commerce" - }, - { - "title": "Kroger", - "id": "kroger.com" - }, - { - "title": "LinkedIn Job Posting", - "id": "linkedin.com-job-posting" - }, - { - "title": "Twitter", - "id": "twitter.com", - "version": "v2" - }, - { - "title": "EasyPost", - "id": "easypost.com" - }, - { - "title": "Galileo Pro", - "id": "galileo.com" - }, - { - "title": "Viessmann", - "id": "viessmann.com" - }, - { - "title": "Magento Enterprise", - "id": "magento.com" - }, - { - "title": "fiserv.dev", - "id": "fiserv.dev" - }, - { - "title": "Okta Admin Management", - "id": "okta.com-admin" - }, - { - "title": "Amazon Selling Partner for Authorization", - "id": "amazon.com-selling-partner-authorization" - }, - { - "title": "Dwolla Balance", - "id": "dwolla.com-balance" - }, - { - "title": "World News", - "id": "worldnewsapi.com" - }, - { - "title": "GoCardless", - "id": "gocardless.com" - }, - { - "title": "Rick and Morty", - "id": "rickandmortyapi.com" - }, - { - "title": "DeepL", - "id": "deepl.com" - }, - { - "title": "SportRadar NFL", - "id": "sportradar.com-nfl", - "version": "v7" - }, - { - "title": "Mailinator", - "id": "mailinator.com" - }, - { - "title": "Clickpost", - "id": "clickpost.com" - }, - { - "title": "Gitlab", - "id": "gitlab.com" - }, - { - "title": "Lemon Markets Data", - "id": "lemon.markets" - }, - { - "title": "ETG Emerging Travel Group", - "id": "emergingtravelgroup.com", - "version": "v3" - }, - { - "title": "Mailgun", - "id": "mailgun.com" - }, - { - "title": "Livechat Agent Chat", - "id": "livechat.com-agent-chat", - "version": "v3.5" - }, - { - "title": "Simple Books", - "id": "simplebooks.com" - }, - { - "title": "TransferWise Send Money", - "id": "wise.com-send-money" - }, - { - "title": "Zoho Sign", - "id": "zoho.com-sign" - }, - { - "title": "Localazy", - "id": "localazy.com" - }, - { - "title": "Zendesk Agent Availabilities", - "id": "zendesk.com-agent-availabilities" - }, - { - "title": "Binance Delivery Futures", - "id": "binance.com-delivery-futures" - }, - { - "title": "QuickChart", - "id": "quickchart.com" - }, - { - "title": "Immoscout24 Search", - "id": "immoscout24.com-search" - }, - { - "title": "Ayrshare Social Media", - "id": "ayrshare.com" - }, - { - "title": "Simple book", - "id": "simplebook.com" - }, - { - "title": "SportRadar Images", - "id": "sportradar.com-images", - "version": "v3" - }, - { - "title": "Celcoin", - "id": "celcoin.com", - "version": "v2" - }, - { - "title": "FHIR", - "id": "fhir.com" - }, - { - "title": "TikAPI", - "id": "tikapi.io", - "version": "v3" - }, - { - "title": "Zendesk Jira Integration", - "id": "zendesk.com-jira-integration" - }, - { - "title": "SportRadar Cricket", - "id": "sportradar.com-cricket", - "version": "v2" - }, - { - "title": "Asana", - "id": "asana.com" - }, - { - "title": "CyberArk OAuth and OpenID Connect", - "id": "cyberark.com-oauth-openid" - }, - { - "title": "OneDrive", - "id": "onedrive.com" - }, - { - "title": "Qualtrics", - "id": "qualtrics.com" - }, - { - "title": "Oracle Object Storage Service", - "id": "oracle.com-object-storage" - }, - { - "title": "ShipStation", - "id": "shipstation.com" - }, - { - "title": "Adyen Configuration", - "id": "adyen.com-configuration", - "version": "v2" - }, - { - "title": "Dyte Documentation", - "id": "dyte.io" - }, - { - "title": "Joomla Web Services", - "id": "joomla.com" - }, - { - "title": "WHOIS XML", - "id": "whoisxmlapi.com" - }, - { - "title": "BoldSign", - "id": "boldsign.com" - }, - { - "title": "GoLogin", - "id": "gologin.com" - }, - { - "title": "Telnyx Phone Numbers", - "id": "telnyx.com-phone-numbers" - }, - { - "title": "Akamai Edge Compute", - "id": "akamai.com-edge-compute" - }, - { - "title": "SPG Checkout", - "id": "spg.com-checkout" - }, - { - "title": "Algorand Algod", - "id": "algorand.com" - }, - { - "title": "SentinelOne", - "id": "sentinelone.com" - }, - { - "title": "Humantic AI", - "id": "humantic.ai" - }, - { - "title": "PDF Generator", - "id": "pdfgeneratorapi.com", - "version": "4.0.0" - }, - { - "title": "MicroStrategy Workflows", - "id": "microstrategy.com-workflows" - }, - { - "title": "Whereby Embedded", - "id": "whereby.com" - }, - { - "title": "Hubspot CRM", - "id": "hubspot.com" - }, - { - "title": "FedEx Track", - "id": "fedex.com-track" - }, - { - "title": "Cloudinary Search", - "id": "cloudinary.com-search" - }, - { - "title": "Infobip SMS", - "id": "infobip.com" - }, - { - "title": "Tastytrade", - "id": "tastytrade.com" - }, - { - "title": "Cal.com", - "id": "cal.com" - }, - { - "title": "ISS MOEX", - "id": "iss.moex.com" - }, - { - "title": "Juniper Mist Runner", - "id": "juniper.net", - "version": "0.3.14.1" - }, - { - "title": "APIBRASIL", - "id": "apibrasil.com", - "version": "v2" - }, - { - "title": "FatSecret", - "id": "fatsecret.com" - }, - { - "title": "Swift Payment Pre-Validation Consumer", - "id": "swift.com-payment-pre-validation" - }, - { - "title": "Adyen Legal Entity Management", - "id": "adyen.com-legal-entity", - "version": "v3" - }, - { - "title": "Ebay", - "id": "ebay.com" - }, - { - "title": "SportRadar Tennis", - "id": "sportradar.com-tennis", - "version": "v3" - }, - { - "title": "Keystone Builder", - "id": "keystone.com" - }, - { - "title": "SportRadar Soccer Extended", - "id": "sportradar.com-soccer-extended", - "version": "v4" - }, - { - "title": "Pardot", - "id": "pardot.com" - }, - { - "title": "Phyllo", - "id": "getphyllo.com" - }, - { - "title": "Braze", - "id": "braze.com" - }, - { - "title": "FortiManager", - "id": "fortinet.com" - }, - { - "title": "GST Compliance", - "id": "gst.com" - }, - { - "title": "SportRadar Formula 1", - "id": "sportradar.com-formula1", - "version": "v2" - }, - { - "title": "Revolut Business", - "id": "revolut.com-business" - }, - { - "title": "Oracle Core Services", - "id": "oracle.com-core-services" - }, - { - "title": "TransferWise Payouts and third party payouts", - "id": "wise.com-payouts" - }, - { - "title": "Typesense", - "id": "typesense.com" - }, - { - "title": "CoinMarketCap DEX", - "id": "coinmarketcap.com-dex" - }, - { - "title": "Vimeo", - "id": "vimeo.com" - }, - { - "title": "Telnyx Messaging", - "id": "telnyx.com-messaging" - }, - { - "title": "CoinMarketCap", - "id": "coinmarketcap.com" - }, - { - "title": "Cisco DNA Center", - "id": "cisco.com-dna-center" - }, - { - "title": "Paystack", - "id": "paystack.com" - }, - { - "title": "Google OAuth2", - "id": "google.com-oauth2" - }, - { - "title": "IHS RME FHIR", - "id": "ihs.com-fhir" - }, - { - "title": "CNPJá!", - "id": "cnpja.com" - }, - { - "title": "AUTENTI", - "id": "autenti.com", - "version": "v2" - }, - { - "title": "COVID19 Tracker", - "id": "covid19tracker.com" - }, - { - "title": "Anvil PDF", - "id": "anvil.com" - }, - { - "title": "Zepto", - "id": "zepto.com" - }, - { - "title": "VIVA Payments Authenticate using basic auth", - "id": "viva.com-authenticate" - }, - { - "title": "SwiftRef", - "id": "swift.com-swiftref" - }, - { - "title": "LinkedIn Apply Connect", - "id": "linkedin.com-apply-connect" - }, - { - "title": "ChangeHealthcare Medical Network Professional Claims", - "id": "changehealthcare.com-medical-network", - "version": "v3" - }, - { - "title": "Auth0 Management", - "id": "auth0.com-management" - }, - { - "title": "Zapsign", - "id": "zapsign.com" - }, - { - "title": "Yodlee", - "id": "yodlee.com" - }, - { - "title": "Perenual", - "id": "perenual.com" - }, - { - "title": "UPS OAuth Client Credentials", - "id": "ups.com-oauth-client-credentials" - }, - { - "title": "Swift GPI Tracker", - "id": "swift.com-gpi-tracker", - "version": "v4" - }, - { - "title": "FRC FirstRobotics Events", - "id": "firstrobotics.com-events" - }, - { - "title": "Adyen Transfers", - "id": "adyen.com-transfers", - "version": "v4" - }, - { - "title": "Scrape.do Web Scraping", - "id": "scrape.do" - }, - { - "title": "WATI", - "id": "wati.com" - }, - { - "title": "MoEngage - Data", - "id": "moengage.com-data" - }, - { - "title": "CheapShark", - "id": "cheapshark.com" - }, - { - "title": "Kong CE Admin", - "id": "kong.com-ce-admin", - "version": "v2.0" - }, - { - "title": "Tatum", - "id": "tatum.io" - }, - { - "title": "HyperSwitch", - "id": "hyperswitch.com" - }, - { - "title": "Sapling AI", - "id": "saplingai.com" - }, - { - "title": "Transfeera", - "id": "transfeera.com" - }, - { - "title": "Canvas FHIR", - "id": "canvasmedical.com-fhir" - }, - { - "title": "Tamara", - "id": "tamara.com", - "version": "v1.0" - }, - { - "title": "Insider", - "id": "useinsider.com" - }, - { - "title": "Salesforce Platform", - "id": "salesforce.com-platform" - }, - { - "title": "Zendesk Talk", - "id": "zendesk.com-talk" - }, - { - "title": "Zuora", - "id": "zuora.com" - }, - { - "title": "HrFlow.ai", - "id": "hrflow.ai" - }, - { - "title": "Speechace", - "id": "speechace.com" - }, - { - "title": "Swift Messaging", - "id": "swift.com-messaging" - }, - { - "title": "TalonOne Integration", - "id": "talonone.com" - }, - { - "title": "Etherscan", - "id": "etherscan.io" - }, - { - "title": "Payoneer Mass Payout", - "id": "payoneer.com-mass-payout" - }, - { - "title": "Stark Bank", - "id": "starkbank.com", - "version": "v2" - }, - { - "title": "VIVA Payments Generate webhook verification key", - "id": "viva.com-webhook-verification" - }, - { - "title": "Customer.io Data Pipelines", - "id": "customer.io" - }, - { - "title": "ZATCA", - "id": "zatca.com" - }, - { - "title": "PingOne Authorize", - "id": "pingone.com-authorize" - }, - { - "title": "Skyscanner B2B", - "id": "skyscanner.com-b2b", - "version": "v3" - }, - { - "title": "Walmart Marketplace", - "id": "walmart.com-marketplace" - }, - { - "title": "Focus NFe", - "id": "focusnfe.com" - }, - { - "title": "Melissa", - "id": "melissa.com" - }, - { - "title": "EODHD Historical Data", - "id": "eodhistoricaldata.com" - }, - { - "title": "Zendesk Webhook", - "id": "zendesk.com-webhook" - }, - { - "title": "Updivision.com", - "id": "updivision.com" - }, - { - "title": "TradingView", - "id": "tradingview.com" - }, - { - "title": "Akool Faceswap Web", - "id": "faceswap akool.com" - }, - { - "title": "Viva Payments Retrieve transactions", - "id": "viva.com-retrieve-transactions", - "version": "v2" - }, - { - "title": "CloudFlare", - "id": "cloudflare.com" - }, - { - "title": "Elasticsearch", - "id": "elasticsearch.com" - }, - { - "title": "Peach Payments Checkout", - "id": "peachpayments.com-checkout" - }, - { - "title": "Zendesk AnswerBot", - "id": "zendesk.com-answerbot" - }, - { - "title": "Zoom Phone", - "id": "zoom.com-phone" - }, - { - "title": "Bitbucket", - "id": "bitbucket.com" - }, - { - "title": "Oracle Identity and Access Management Service", - "id": "oracle.com-identity-access-management" - }, - { - "title": "Flagsmith", - "id": "flagsmith.com" - }, - { - "title": "CyberArk Identity", - "id": "cyberark.com-identity" - }, - { - "title": "Mailjet", - "id": "mailjet.com" - }, - { - "title": "LinkedIn Audiences", - "id": "linkedin.com-audiences" - }, - { - "title": "FedEx Ship", - "id": "fedex.com-ship" - }, - { - "title": "FedEx Rates and Transit Times", - "id": "fedex.com-rates-transit-times" - }, - { - "title": "Telnyx Call Control", - "id": "telnyx.com-call-control" - }, - { - "title": "AWS Amazon Web Services Cognito Identity Provider", - "id": "amazon.com-cognito-identity-provider" - }, - { - "title": "Customer.io Journeys App", - "id": "customer.io-journeys" - }, - { - "title": "Adyen Management", - "id": "adyen.com-management", - "version": "v3" - }, - { - "title": "Frontapp Core", - "id": "frontapp.com-core" - }, - { - "title": "Change Healthcare Medical Network Claim Status", - "id": "changehealthcare.com-claim-status", - "version": "v2" - }, - { - "title": "Call of Duty", - "id": "callofduty.com" - }, - { - "title": "UPS Shipping", - "id": "ups.com-shipping" - }, - { - "title": "Geonode", - "id": "geonode.com" - }, - { - "title": "Gusto", - "id": "gusto.com" - }, - { - "title": "Primary Trading", - "id": "primary.com" - }, - { - "title": "UPS OAuth Auth Code", - "id": "ups.com-oauth-auth-code" - }, - { - "title": "Amazon Selling Partner Catalog Items", - "id": "amazon.com-selling-partner-catalog-items" - }, - { - "title": "SYSCOM", - "id": "syscom.com" - }, - { - "title": "Gitlab CI CD", - "id": "gitlab.com-ci-cd" - }, - { - "title": "SportRadar MMA", - "id": "sportradar.com-mma", - "version": "v2" - }, - { - "title": "HIKVISION", - "id": "hikvision.com" - }, - { - "title": "Productboard", - "id": "productboard.com" - }, - { - "title": "Infobip WhatsApp", - "id": "infobip.com-whatsapp" - }, - { - "title": "Drophub", - "id": "drophub.com" - }, - { - "title": "AvaTax", - "id": "avalara.com" - }, - { - "title": "Revolut Merchant", - "id": "revolut.com-merchant" - }, - { - "title": "Wildberries", - "id": "wildberries.com" - }, - { - "title": "Solcast", - "id": "solcast.com" - }, - { - "title": "AWS Amazon Web Services EC2", - "id": "amazon.com-ec2" - }, - { - "title": "Rutter Commerce", - "id": "rutter.com-commerce" - }, - { - "title": "Mastercard BIN Lookup", - "id": "mastercard.com-bin-lookup" - }, - { - "title": "Acronis Account Management", - "id": "acronis.com-account-management" - }, - { - "title": "IBANAPI", - "id": "ibanapi.com" - }, - { - "title": "MongoDB Data", - "id": "mongodb.com-data-api" - }, - { - "title": "Fastly", - "id": "fastly.com" - }, - { - "title": "Payoneer Mass Payout & Services", - "id": "payoneer.com-mass-payout-services" - }, - { - "title": "Mastercard Open Banking US", - "id": "mastercard.com-open-banking" - }, - { - "title": "Durianpay Merchant", - "id": "durianpay.com-merchant", - "version": "v1" - }, - { - "title": "Opsgenie", - "id": "opsgenie.com" - }, - { - "title": "Cisco SD WAN AlwaysOn", - "id": "cisco.com-sd-wan-alwayson" - }, - { - "title": "Zoho Desk", - "id": "zoho.com-desk" - }, - { - "title": "Data.World", - "id": "data.world" - }, - { - "title": "Immoscout24 Import/Export", - "id": "immoscout24.com-import-export" - }, - { - "title": "Klaviyo", - "id": "klaviyo.com", - "version": "v2024-02-15" - }, - { - "title": "Shyft", - "id": "shyft.com", - "version": "v1" - }, - { - "title": "Twitter Ads", - "id": "twitter.com-ads" - }, - { - "title": "Plant.id", - "id": "plant.id", - "version": "v3" - }, - { - "title": "Immoscout24 Expose", - "id": "immoscout24.com-expose" - }, - { - "title": "SW", - "id": "sw.com" - }, - { - "title": "Tyk Gateway", - "id": "tyk.com-gateway", - "version": "v3.2.1" - }, - { - "title": "LiveChat Customer Chat", - "id": "livechat.com-customer-chat", - "version": "v3.5" - }, - { - "title": "Monoova Payments Platform", - "id": "monoova.com" - }, - { - "title": "Africa's Talking Bulk SMS", - "id": "africastalking.com-bulk-sms" - }, - { - "title": "DocuSign Rooms", - "id": "docusign.com-rooms", - "version": "v2" - }, - { - "title": "Viva.com Cloud", - "id": "viva.com-cloud" - }, - { - "title": "FPL Fantasy Premier League", - "id": "fantasy.premierleague.com" - }, - { - "title": "Metapack Shipping", - "id": "metapack.com-shipping" - }, - { - "title": "iRacing", - "id": "iracing.com" - }, - { - "title": "LinkedIn Recruiter System Connect", - "id": "linkedin.com-recruiter-system-connect" - }, - { - "title": "Duo", - "id": "duo.com" - }, - { - "title": "Akamai Reporting", - "id": "akamai.com-reporting" - }, - { - "title": "Merge HRIS", - "id": "merge.com-hris" - }, - { - "title": "Frappe ERPNext", - "id": "frappe.com" - }, - { - "title": "DHRU FUSION CLIENT", - "id": "dhru.com-fusion-client", - "version": "v2" - }, - { - "title": "Vultr", - "id": "vultr.com", - "version": "v2" - }, - { - "title": "Bigin", - "id": "bigin.com" - }, - { - "title": "Salesforce Data Cloud Connect", - "id": "salesforce.com-data-cloud-connect" - }, - { - "title": "SportRadar Odds Comparison Regular", - "id": "sportradar.com-odds-comparison-regular", - "version": "v1" - }, - { - "title": "Imdb", - "id": "imdb.com" - }, - { - "title": "JP Hotel", - "id": "jp.com-hotel" - }, - { - "title": "Adobe Acrobat Sign", - "id": "adobe.com-acrobat-sign" - }, - { - "title": "Etsy", - "id": "etsy.com" - }, - { - "title": "Jamf Pro", - "id": "jamf.com-pro", - "version": "v11.2.0" - }, - { - "title": "VAPIX", - "id": "vapix.com" - }, - { - "title": "TransferWise", - "id": "wise.com" - }, - { - "title": "Etherscan Tokens", - "id": "etherscan.com-tokens" - }, - { - "title": "Firely Server", - "id": "firely.com-server" - }, - { - "title": "Fine-Tuner", - "id": "fine-tuner.com" - }, - { - "title": "Commvault", - "id": "commvault.com" - }, - { - "title": "BigCommerce", - "id": "bigcommerce.com", - "version": "v3" - }, - { - "title": "Dropbox Sign", - "id": "dropbox.com-sign" - }, - { - "title": "TransferWise Partner Account", - "id": "wise.com-partner-account" - }, - { - "title": "Stytch", - "id": "stytch.com" - }, - { - "title": "Plaid Core Exchange", - "id": "plaid.com-core-exchange" - }, - { - "title": "Okta OpenID Connect & OAuth", - "id": "okta.com-openid-connect-oauth-2" - }, - { - "title": "Orange Sonatel", - "id": "orange-sonatel.com" - }, - { - "title": "SportRadar MLB", - "id": "sportradar.com-mlb", - "version": "v7" - }, - { - "title": "Bandwidth", - "id": "bandwidth.com", - "version": "v1" - }, - { - "title": "Venus", - "id": "venus.com" - }, - { - "title": "Akamai Edge Diagnostics", - "id": "akamai.com-edge-diagnostics" - }, - { - "title": "Amazon Selling Partner Reports", - "id": "amazon.com-selling-partner-reports" - }, - { - "title": "CoinMarketCal", - "id": "coinmarketcal.com" - }, - { - "title": "SportRadar NCAA Men's Basketball", - "id": "sportradar.com-ncaa-mens-basketball", - "version": "v8" - }, - { - "title": "Imperva", - "id": "imperva.com" - }, - { - "title": "NewsCatcher News", - "id": "newscatcher.com", - "version": "v2" - }, - { - "title": "Oracle Hospitality Property", - "id": "oracle.com-hospitality-property" - }, - { - "title": "Route Mobile WhatsApp Business Messaging", - "id": "routemobile.com-whatsapp-business-messaging" - }, - { - "title": "Sudo.Cards", - "id": "sudo.cards" - }, - { - "title": "Autodesk PWS Sales & Customer Success", - "id": "autodesk.com-pws-sales-customer-success" - }, - { - "title": "Google Vision", - "id": "google.com-vision" - }, - { - "title": "NetSuite", - "id": "netsuite.com" - }, - { - "title": "PayPal Payouts", - "id": "paypal.com-payouts" - }, - { - "title": "Cisco ISE ERS", - "id": "cisco.com-ise-ers" - }, - { - "title": "Huawei AppGallery Connect", - "id": "huawei.com-appgallery-connect" - }, - { - "title": "CoWIN", - "id": "cowin.gov.in" - }, - { - "title": "Veeva Vault", - "id": "veeva.com-vault", - "version": "v23.3" - }, - { - "title": "Swagger Petstore", - "id": "swagger.io-petstore" - }, - { - "title": "Sendbird Calls", - "id": "sendbird.com-calls" - }, - { - "title": "GP GlobalProduct", - "id": "globalproduct.com" - }, - { - "title": "Microsoft Graph Certificate Auth", - "id": "microsoft.com-graph-certificate-auth" - }, - { - "title": "Amazon Payment Services", - "id": "amazonpaymentservices.com" - }, - { - "title": "Moodle", - "id": "moodle.com" - }, - { - "title": "Oracle Cloud Infrastructure Language", - "id": "oracle.com-cloud-infrastructure-language" - }, - { - "title": "SportRadar Odds Comparison Player Props", - "id": "sportradar.com-odds-comparison-player-props", - "version": "v2" - }, - { - "title": "Telnyx Number Lookup", - "id": "telnyx.com-number-lookup" - }, - { - "title": "Football-data.org", - "id": "football-data.org", - "version": "v4" - }, - { - "title": "Nigeria Open Banking", - "id": "openbankingnigeria.com", - "version": "v1" - }, - { - "title": "Bitly", - "id": "bitly.com" - }, - { - "title": "dbt Cloud Object Management", - "id": "dbt.com-cloud-object-management" - }, - { - "title": "Treasury Prime", - "id": "treasuryprime.com" - }, - { - "title": "Tiktok Traffic Objective", - "id": "tiktok.com-traffic-objective" - }, - { - "title": "UPS Tracking", - "id": "ups.com-tracking" - }, - { - "title": "Loket", - "id": "loket.com" - }, - { - "title": "Signeasy eSignature", - "id": "signeasy.com", - "version": "v3.0" - }, - { - "title": "Bolt", - "id": "bolt.com" - }, - { - "title": "Akool Faceswap Web", - "id": "akool.com-faceswap-web" - }, - { - "title": "SmartOLT", - "id": "smartolt.com" - }, - { - "title": "TransferWise Wise for Banks", - "id": "wise.com-banks" - }, - { - "title": "Tellelabs", - "id": "tellelabs.com" - }, - { - "title": "Pagar.me", - "id": "pagar.me", - "version": "v5" - }, - { - "title": "Docker Engine", - "id": "docker.com-engine" - }, - { - "title": "CyberArk Identity User Management", - "id": "cyberark.com-identity-user-management" - }, - { - "title": "Gong", - "id": "gong.com" - }, - { - "title": "Google Cloud Firestore", - "id": "google.com-firestore" - }, - { - "title": "OpenWeatherMap", - "id": "openweathermap.com" - }, - { - "title": "ManageEngine - ServiceDesk plus", - "id": "manageengine.com-servicedeskplus" - }, - { - "title": "UPS Rating", - "id": "ups.com-rating" - }, - { - "title": "Pricempire.com", - "id": "pricempire.com" - }, - { - "title": "PandaScore", - "id": "pandascore.com" - }, - { - "title": "QuickBooks Online", - "id": "quickbooks.com" - }, - { - "title": "LiveChat Configuration", - "id": "livechat.com-configuration", - "version": "v3.5" - }, - { - "title": "Merge Accounting", - "id": "merge.com" - }, - { - "title": "JAMF", - "id": "jamf.com", - "version": "v10.49.0" - }, - { - "title": "VMWare vSphere Automation", - "id": "vmware.com-vcenter" - }, - { - "title": "VMWare Carbon Black", - "id": "vmware.com-carbon-black" - }, - { - "title": "Midjourney", - "id": "midjourney.com", - "version": "v2" - }, - { - "title": "LinkedIn Lead Sync", - "id": "linkedin.com-lead-sync", - "version": "v2" - }, - { - "title": "SailPoint IdentityNow NERM", - "id": "sailpoint.com-identitynow-nerm" - }, - { - "title": "Microsoft SharePoint", - "id": "microsoft.com-sharepoint" - }, - { - "title": "VTEX", - "id": "vtex.com" - }, - { - "title": "Appcues", - "id": "appcues.com", - "version": "v2" - }, - { - "title": "Airalo Partner", - "id": "airalo.com-partner" - }, - { - "title": "Bond", - "id": "bond.com" - }, - { - "title": "Mattermost", - "id": "mattermost.com" - }, - { - "title": "Tenable Vulnerability Management", - "id": "tenable.com-vulnerability-management" - }, - { - "title": "Tenable WAS Web Application Scanning", - "id": "tenable.com-was" - }, - { - "title": "Tenable Platform", - "id": "tenable.com-platform" - }, - { - "title": "Tenable MSSP Managed Security Service Provider", - "id": "tenable.com-mssp" - }, - { - "title": "Tenable Downloads", - "id": "tenable.com-downloads" - }, - { - "title": "Tenable Container Security", - "id": "tenable.com-container-security" - }, - { - "title": "Cisco Webex Messaging", - "id": "cisco.com-webex-messaging" - }, - { - "title": "Cisco SD WAN", - "id": "cisco.com-sd-wan" - }, - { - "title": "Cisco Umbrella", - "id": "cisco.com-umbrella" - }, - { - "title": "Cisco Meraki Webhooks Management", - "id": "cisco.com-meraki-webhooks" - }, - { - "title": "Cisco Meraki", - "id": "cisco.com-meraki" - }, - { - "title": "Cisco Webex Meetings", - "id": "cisco.com-webex-meetings" - }, - { - "title": "Cisco Secure Firewall Management Center (FMC)", - "id": "cisco.com-secure-firewall-management-center" - }, - { - "title": "Arsha BDO Market", - "id": "arsha.io-bdo-market" - }, - { - "title": "Tremendous", - "id": "tremendous.com" - }, - { - "title": "GMB Row", - "id": "gmb.com-row" - }, - { - "title": "Pluggy", - "id": "pluggy.com" - }, - { - "title": "Fortinet Fortimanager", - "id": "fortinet.com-fortimanager" - }, - { - "title": "Hybrid Analysis", - "id": "hybrid-analysis.com" - }, - { - "title": "Trellix ePO", - "id": "trellix.com-epo" - }, - { - "title": "Trellix IVX", - "id": "trellix.com-ivx" - }, - { - "title": "Trellix DLP", - "id": "trellix.com-dlp" - }, - { - "title": "Greynoise", - "id": "greynoise.io" - }, - { - "title": "Greynoise Enterprise", - "id": "greynoise.io-enterprise" - }, - { - "title": "Azure Resource Management", - "id": "azure.com-resource-management" - }, - { - "title": "Exotel Voice", - "id": "exotel.com-voice", - "version": "v1" - }, - { - "title": "Github", - "id": "github.com" - }, - { - "title": "Lipseys", - "id": "lipseys.com" - }, - { - "title": "R-Series Authentication", - "id": "lightspeed.com-r-series-authentication" - }, - { - "title": "Skyscanner Referrals", - "id": "skyscanner.com-referrals" - }, - { - "title": "Swift GPI Transaction Details", - "id": "swift.com-gpi-transaction-details" - }, - { - "title": "Luxand Cloud", - "id": "luxand.cloud" - }, - { - "title": "Sonatel QRCODE OM", - "id": "sonatel.com-qrcode-om" - }, - { - "title": "Keycloak", - "id": "keycloak.com" - }, - { - "title": "Veriff", - "id": "veriff.com", - "version": "v1.0" - }, - { - "title": "Transak", - "id": "transak.com" - }, - { - "title": "Auth0", - "id": "auth0.com" - }, - { - "title": "Google Search Console", - "id": "google.com-search-console" - }, - { - "title": "PAN Palo Alto Networks PAN-OS XML", - "id": "paloaltonetworks.com-pan-os-xml" - }, - { - "title": "PAN Palo Alto Networks Cloud Services Status", - "id": "paloaltonetworks.com-cloud-services-status" - }, - { - "title": "PAN Palo Alto Networks Licensing", - "id": "paloaltonetworks.com-licensing" - }, - { - "title": "PAN Palo Alto Networks Prisma Cloud", - "id": "paloaltonetworks.com-prisma-cloud" - }, - { - "title": "AWS Amazon Web Services Security Token Service", - "id": "aws.com-security-token-service" - }, - { - "title": "FHIRFLY", - "id": "fhirfly.com" - }, - { - "title": "Okta Policy", - "id": "okta.com-policy" - }, - { - "title": "Paypal Sandbox Paths", - "id": "paypal.com-sandbox-paths" - }, - { - "title": "onlinesim.ru Receiving SMS", - "id": "onlinesim.ru-receiving-sms" - }, - { - "title": "LightSpeedHQ R-Series Inventory", - "id": "lightspeed.com-r-series-inventory" - }, - { - "title": "Akamai Certificate Provisioning System", - "id": "akamai.com-certificate-provisioning-system" - }, - { - "title": "Knock", - "id": "knock.com" - }, - { - "title": "Acrgis Data hosting", - "id": "arcgis.com-data-hosting" - }, - { - "title": "Alpha Vantage", - "id": "alpha-vantage.com" - }, - { - "title": "Anaplan", - "id": "anaplan.com" - }, - { - "title": "MoMo E-Wallet Recurring Payments", - "id": "momo.com-recurring-payments" - }, - { - "title": "Ethereum JSON-RPC", - "id": "ethereum.com-json-rpc" - }, - { - "title": "SurrealDB", - "id": "surrealdb.com" - }, - { - "title": "360Dialog Integrated Onboarding Partner", - "id": "360dialog.com-integrated-onboarding-partner" - }, - { - "title": "Opencep", - "id": "opencep.com" - }, - { - "title": "TravelTime", - "id": "traveltime.com" - }, - { - "title": "Power BI Embedded Azure Resource Manager", - "id": "powerbi.com-embedded-azure-resource-manager", - "version": "v2017-10-01" - }, - { - "title": "LinkedIn Apply With", - "id": "linkedin.com-apply-with", - "version": "v3" - }, - { - "title": "DataCite", - "id": "datacite.com" - }, - { - "title": "Flight", - "id": "flight.com", - "version": "v1" - }, - { - "title": "Stuart", - "id": "stuart.com" - }, - { - "title": "Aiia", - "id": "aiia.com" - }, - { - "title": "Argyle", - "id": "argyle.com", - "version": "v2" - }, - { - "title": "r/SpaceX", - "id": "spacexdata.com" - }, - { - "title": "Peach Payments", - "id": "peachpayments.com" - }, - { - "title": "Revolut Open Banking", - "id": "revolut.com-open-banking" - }, - { - "title": "Coinbase", - "id": "coinbase.com" - }, - { - "title": "AWS Amazon Web Services DynamoDB", - "id": "aws.com-dynamodb" - }, - { - "title": "Azure DevOps", - "id": "azure.com-devops", - "version": "v5.0" - }, - { - "title": "NinjaOne", - "id": "ninjaone.com", - "version": "v2.0" - }, - { - "title": "Salla Merchant", - "id": "salla.com-merchant" - }, - { - "title": "USPS Web Tools Track and Confirm", - "id": "usps.com-track-and-confirm" - }, - { - "title": "Cartes.io", - "id": "cartes.io" - }, - { - "title": "Oracle Monitoring", - "id": "oracle.com-monitoring" - }, - { - "title": "DynamicDocs JSON to PDF Templates", - "id": "dynamicdocs.com-json-to-pdf-templates" - }, - { - "title": "DuckDuckGo Instant Answer", - "id": "duckduckgo.com-instant-answer" - }, - { - "title": "TikTok Shop Open", - "id": "tiktok.com-shop-open" - }, - { - "title": "Rasa X HTTP", - "id": "rasa.com-x-http" - }, - { - "title": "Adyen Balance Control", - "id": "adyen.com-balance-control", - "version": "v1" - }, - { - "title": "Shopware Admin", - "id": "shopware.com-admin", - "version": "6" - }, - { - "title": "PrestaShop eCommerce", - "id": "prestashop.com-ecommerce" - }, - { - "title": "Transferwise Wise Partner KYC Platform", - "id": "wise.com-wise-partner-kyc" - }, - { - "title": "8/24 NexHealth Synchronizer", - "id": "nexhealth.com-synchronizer" - }, - { - "title": "MessageBird", - "id": "messagebird.com" - }, - { - "title": "Rapid7 InsightVM", - "id": "rapid7.com-insightvm" - }, - { - "title": "NICE CXone - User Hub NA1", - "id": "nice.com-user-hub-na1" - }, - { - "title": "Cora Bank", - "id": "corabank.com" - }, - { - "title": "Universign Transactions", - "id": "universign.com-transactions" - }, - { - "title": "Delhivery", - "id": "delhivery.com" - }, - { - "title": "Envia Shipping Multi Carrier Solution for Ecommerce", - "id": "envia.com" - }, - { - "title": "LiveChat Reports", - "id": "livechat.com-reports", - "version": "v3.5" - }, - { - "title": "RingCentral", - "id": "ringcentral.com" - }, - { - "title": "ComplyCube", - "id": "complycube.com", - "version": "v1" - }, - { - "title": "pVerify", - "id": "pverify.com" - }, - { - "title": "Swift GPI Customer Credit Transfer", - "id": "swift.com-gpi-customer-credit-transfer" - }, - { - "title": "Backblaze B2 Cloud Storage S3 Compatible", - "id": "backblaze.com-b2-cloud-storage-s3-compatible" - }, - { - "title": "SportRadar NCAA Men's Football", - "id": "ncaa.com-mens-football", - "version": "v7" - }, - { - "title": "Opencart Shopping Cart", - "id": "opencart.com" - }, - { - "title": "Smartcar", - "id": "smartcar.com" - }, - { - "title": "Instapack Instagram", - "id": "instapack.com-instagram" - }, - { - "title": "Adyen Checkout", - "id": "adyen.com-checkout2" - }, - { - "title": "Arcgis Demographics & GeoEnrichment", - "id": "arcgis.com-demographics-geoenrichment" - }, - { - "title": "Zendesk JWT Authentication", - "id": "zendesk.com-jwt-authentication" - }, - { - "title": "Mercadopago Checkout PRO", - "id": "mercadopago.com-checkout-pro" - }, - { - "title": "ReqRes", - "id": "reqres.com" - }, - { - "title": "SPG Get Status", - "id": "spg.com-get-status" - }, - { - "title": "Miro", - "id": "miro.com" - }, - { - "title": "GSM Arena", - "id": "gsmarena.com" - }, - { - "title": "WeChat Pay", - "id": "wechat.com-pay-v3", - "version": "v3" - }, - { - "title": "Riot", - "id": "riot.com" - }, - { - "title": "Zendesk Sunshine Events", - "id": "zendesk.com-sunshine-events" - }, - { - "title": "TourInSoft Syndications Webservice", - "id": "tourinsoft.com-syndications-webservice-v3", - "version": "v3" - }, - { - "title": "LightSpeed K-Series", - "id": "lightspeed.com-k-series" - }, - { - "title": "Commerce Layer Core", - "id": "commercelayer.com-core", - "version": "2024-03-12" - }, - { - "title": "Wemeet OAuth", - "id": "wemeet.com-oauth" - }, - { - "title": "Banxa", - "id": "banxa.com" - }, - { - "title": "Transferwise Wise Multi-Currency Account", - "id": "wise.com-multi-currency-account" - }, - { - "title": "AWS Amazon Web Services Simple Email Service", - "id": "aws.com-simple-email-service" - }, - { - "title": "Akamai Billing", - "id": "akamai.com-billing" - }, - { - "title": "Twilio Webhook", - "id": "twilio.com-webhook" - }, - { - "title": "Bungie.Net", - "id": "bungie.net" - }, - { - "title": "Transfeera ContaCerta", - "id": "transfeera.com-contacerta" - }, - { - "title": "Oracle Vision", - "id": "oracle.com-vision" - }, - { - "title": "CEX.io", - "id": "cex.io" - }, - { - "title": "UPS Address Validation", - "id": "ups.com-address-validation" - }, - { - "title": "SPG MB REFERENCE", - "id": "spg.com-mb-reference" - }, - { - "title": "Infobip Email", - "id": "infobip.com-email" - }, - { - "title": "Forte", - "id": "forte.com-rest-v3", - "version": "v3" - }, - { - "title": "TaxJar SmartCalcs", - "id": "taxjar.com-smartcalcs" - }, - { - "title": "ChangeHealthcare Medical Network Claims Responses and Reports", - "id": "changehealthcare.com-claims-responses-and-reports", - "version": "v2" - }, - { - "title": "Senapedia", - "id": "senapedia.com" - }, - { - "title": "Zoho Subscriptions", - "id": "zoho.com-subscriptions" - }, - { - "title": "Jasmin", - "id": "jasminsoftware.com" - }, - { - "title": "Huawei AGC AppGallery Connect Publishing", - "id": "huawei.com-appgallery-connect-publishing" - }, - { - "title": "Zendesk Unified Agent Status", - "id": "zendesk.com-unified-agent-status" - }, - { - "title": "Zoom Chatbot", - "id": "zoom.com-chatbot" - }, - { - "title": "Hashicorp Vault", - "id": "hashicorp.com-vault" - }, - { - "title": "SailPoint IdentityNow SCIM", - "id": "sailpoint.com-identitynow-scim" - }, - { - "title": "OMDb Open Movie Database", - "id": "omdbapi.com" - }, - { - "title": "FIWARE", - "id": "fiware.com" - }, - { - "title": "Merge ATS", - "id": "merge.com-ats" - }, - { - "title": "HuggingFace Datasets", - "id": "huggingface.co-datasets" - }, - { - "title": "Quotable", - "id": "quotable.com" - }, - { - "title": "ActiveFence", - "id": "activefence.com" - }, - { - "title": "NS NeuralSpace", - "id": "neuralspace.com" - }, - { - "title": "Rev AI", - "id": "rev.com" - }, - { - "title": "Akamai Identity and Access Management", - "id": "akamai.com-identity-and-access-management", - "version": "v3" - }, - { - "title": "Twilio SendGrid", - "id": "sendgrid.com-v3", - "version": "v3" - }, - { - "title": "Intercom", - "id": "intercom.com", - "version": "2.10" - }, - { - "title": "Microsoft Entra VerifiedID Request", - "id": "microsoft.com-entra-verifiedid-request" - }, - { - "title": "Twilio Messaging SMS", - "id": "twilio.com-messaging-sms" - }, - { - "title": "AlienVault OTX", - "id": "otx.alienvault.com" - }, - { - "title": "Qualys", - "id": "qualys.com" - }, - { - "title": "Recorded Future", - "id": "recordedfuture.com" - } -] diff --git a/packages/cli/src/services/ai/schemas/generateCurl.ts b/packages/cli/src/services/ai/schemas/generateCurl.ts deleted file mode 100644 index e5f9c8ccf3..0000000000 --- a/packages/cli/src/services/ai/schemas/generateCurl.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { z } from 'zod'; - -export const generateCurlSchema = z.object({ - curl: z - .string() - .describe('The curl command that the user could run to call the endpoint they described.'), -}); diff --git a/packages/cli/src/services/ai/schemas/retrieveService.ts b/packages/cli/src/services/ai/schemas/retrieveService.ts deleted file mode 100644 index 6d2b187ded..0000000000 --- a/packages/cli/src/services/ai/schemas/retrieveService.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { z } from 'zod'; - -export const retrieveServiceSchema = z.object({ - id: z - .string() - .describe( - 'The id of the service, has to match the `id` of one of the entries in the CSV file or empty string', - ), -}); diff --git a/packages/cli/src/services/ai/utils/summarizeNodeTypeProperties.ts b/packages/cli/src/services/ai/utils/summarizeNodeTypeProperties.ts deleted file mode 100644 index 27fb90197a..0000000000 --- a/packages/cli/src/services/ai/utils/summarizeNodeTypeProperties.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable @typescript-eslint/no-use-before-define */ -import type { INodeProperties, INodePropertyCollection, INodePropertyOptions } from 'n8n-workflow'; - -export function summarizeOption( - option: INodePropertyOptions | INodeProperties | INodePropertyCollection, -): Partial { - if ('value' in option) { - return { - name: option.name, - value: option.value, - }; - } else if ('values' in option) { - return { - name: option.name, - values: option.values.map(summarizeProperty) as INodeProperties[], - }; - } else { - return summarizeProperty(option); - } -} - -export function summarizeProperty(property: INodeProperties): Partial { - return { - name: property.displayName, - type: property.type, - ...(property.displayOptions ? { displayOptions: property.displayOptions } : {}), - ...((property.options - ? { options: property.options.map(summarizeOption) } - : {}) as INodeProperties['options']), - }; -} - -export function summarizeNodeTypeProperties(nodeTypeProperties: INodeProperties[]) { - return nodeTypeProperties.map(summarizeProperty); -} diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index 0f7a9167e1..f977d1e0b2 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -216,10 +216,6 @@ export class FrontendService { }, ai: { enabled: config.getEnv('ai.enabled'), - provider: config.getEnv('ai.provider'), - features: { - generateCurl: !!config.getEnv('ai.openAI.apiKey'), - }, }, workflowHistory: { pruneTime: -1, diff --git a/packages/cli/src/types/ai.types.ts b/packages/cli/src/types/ai.types.ts deleted file mode 100644 index be072d198b..0000000000 --- a/packages/cli/src/types/ai.types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { BaseMessageChunk, BaseMessageLike } from '@langchain/core/messages'; -import type { BaseChatModelCallOptions } from '@langchain/core/language_models/chat_models'; - -export interface N8nAIProvider { - invoke(message: BaseMessageLike[], options?: BaseChatModelCallOptions): Promise; - mapResponse(data: BaseMessageChunk): string; -} diff --git a/packages/cli/test/unit/services/ai.service.test.ts b/packages/cli/test/unit/services/ai.service.test.ts deleted file mode 100644 index 2f93faa13a..0000000000 --- a/packages/cli/test/unit/services/ai.service.test.ts +++ /dev/null @@ -1,225 +0,0 @@ -import { ApplicationError, jsonParse } from 'n8n-workflow'; -import { AIService } from '@/services/ai.service'; -import config from '@/config'; -import { - generateCurlCommandFallbackPromptTemplate, - generateCurlCommandPromptTemplate, -} from '@/services/ai/prompts/generateCurl'; -import { PineconeStore } from '@langchain/pinecone'; - -jest.mock('@/config', () => { - return { - getEnv: jest.fn().mockReturnValue('openai'), - }; -}); - -jest.mock('langchain/output_parsers', () => { - return { - JsonOutputFunctionsParser: jest.fn().mockImplementation(() => { - return { - parse: jest.fn(), - }; - }), - }; -}); - -jest.mock('@langchain/pinecone', () => { - const similaritySearch = jest.fn().mockImplementation(async () => []); - - return { - PineconeStore: { - similaritySearch, - fromExistingIndex: jest.fn().mockImplementation(async () => ({ - similaritySearch, - })), - }, - }; -}); - -jest.mock('@pinecone-database/pinecone', () => ({ - Pinecone: jest.fn().mockImplementation(() => ({ - Index: jest.fn().mockImplementation(() => ({})), - })), -})); - -jest.mock('@/services/ai/providers/openai', () => { - const modelInvoke = jest.fn().mockImplementation(() => ({ curl: 'curl -X GET https://n8n.io' })); - - return { - AIProviderOpenAI: jest.fn().mockImplementation(() => { - return { - mapResponse: jest.fn((v) => v), - invoke: modelInvoke, - model: { - invoke: modelInvoke, - }, - modelWithOutputParser: () => ({ - invoke: modelInvoke, - }), - }; - }), - }; -}); - -afterEach(() => { - jest.clearAllMocks(); -}); - -describe('AIService', () => { - describe('constructor', () => { - test('should not assign provider with unknown provider type', async () => { - jest.mocked(config).getEnv.mockReturnValue('unknown'); - const aiService = new AIService(); - - expect(aiService.provider).not.toBeDefined(); - }); - }); - - describe('prompt', () => { - test('should throw if prompting with unknown provider type', async () => { - jest.mocked(config).getEnv.mockReturnValue('unknown'); - - const aiService = new AIService(); - - await expect(async () => await aiService.prompt([])).rejects.toThrow(ApplicationError); - }); - - test('should call provider.invoke', async () => { - jest.mocked(config).getEnv.mockReturnValue('openai'); - - const service = new AIService(); - await service.prompt(['message']); - - expect(service.provider.invoke).toHaveBeenCalled(); - }); - }); - - describe('generateCurl', () => { - test('should call generateCurl fallback if pinecone key is not defined', async () => { - jest.mocked(config).getEnv.mockImplementation((key: string) => { - if (key === 'ai.pinecone.apiKey') { - return undefined; - } - - return 'openai'; - }); - - const service = new AIService(); - const generateCurlGenericSpy = jest.spyOn(service, 'generateCurlGeneric'); - service.validateCurl = (v) => v; - - const serviceName = 'Service Name'; - const serviceRequest = 'Please make a request'; - - await service.generateCurl(serviceName, serviceRequest); - - expect(generateCurlGenericSpy).toHaveBeenCalled(); - }); - - test('should call generateCurl fallback if no matched service', async () => { - jest.mocked(config).getEnv.mockReturnValue('openai'); - - const service = new AIService(); - const generateCurlGenericSpy = jest.spyOn(service, 'generateCurlGeneric'); - service.validateCurl = (v) => v; - - const serviceName = 'NoMatchedServiceName'; - const serviceRequest = 'Please make a request'; - - await service.generateCurl(serviceName, serviceRequest); - - expect(generateCurlGenericSpy).toHaveBeenCalled(); - }); - - test('should call generateCurl fallback command if no matched vector store documents', async () => { - jest.mocked(config).getEnv.mockReturnValue('openai'); - - const service = new AIService(); - const generateCurlGenericSpy = jest.spyOn(service, 'generateCurlGeneric'); - service.validateCurl = (v) => v; - - const serviceName = 'OpenAI'; - const serviceRequest = 'Please make a request'; - - await service.generateCurl(serviceName, serviceRequest); - - expect(generateCurlGenericSpy).toHaveBeenCalled(); - }); - - test('should call generateCurl command with documents from vectorStore', async () => { - const endpoints = [ - { - id: '1', - title: 'OpenAI', - pageContent: '{ "example": "value" }', - }, - ]; - const serviceName = 'OpenAI'; - const serviceRequest = 'Please make a request'; - - jest.mocked(config).getEnv.mockReturnValue('openai'); - jest - .mocked((PineconeStore as unknown as { similaritySearch: () => {} }).similaritySearch) - .mockImplementation(async () => endpoints); - - const service = new AIService(); - service.validateCurl = (v) => v; - - await service.generateCurl(serviceName, serviceRequest); - - const messages = await generateCurlCommandPromptTemplate.formatMessages({ - serviceName, - serviceRequest, - endpoints: JSON.stringify(endpoints.map((document) => jsonParse(document.pageContent))), - }); - - expect(service.provider.model.invoke).toHaveBeenCalled(); - expect(service.provider.model.invoke.mock.calls[0][0].messages).toEqual(messages); - }); - }); - - describe('generateCurlGeneric', () => { - test('should call prompt with serviceName and serviceRequest', async () => { - const serviceName = 'Service Name'; - const serviceRequest = 'Please make a request'; - - const service = new AIService(); - service.validateCurl = (v) => v; - - await service.generateCurlGeneric(serviceName, serviceRequest); - - const messages = await generateCurlCommandFallbackPromptTemplate.formatMessages({ - serviceName, - serviceRequest, - }); - - expect(service.provider.model.invoke).toHaveBeenCalled(); - expect(jest.mocked(service.provider.model.invoke).mock.calls[0][0].messages).toEqual( - messages, - ); - }); - }); - - describe('validateCurl', () => { - it('should return the result if curl command starts with "curl"', () => { - const aiService = new AIService(); - const result = { curl: 'curl -X GET https://n8n.io' }; - const validatedResult = aiService.validateCurl(result); - expect(validatedResult).toEqual(result); - }); - - it('should replace boolean and number placeholders in the curl command', () => { - const aiService = new AIService(); - const result = { curl: 'curl -X GET https://n8n.io -d "{ "key": {{value}} }"' }; - const expected = { curl: 'curl -X GET https://n8n.io -d "{ "key": "{{value}}" }"' }; - const validatedResult = aiService.validateCurl(result); - expect(validatedResult).toEqual(expected); - }); - - it('should throw an error if curl command does not start with "curl"', () => { - const aiService = new AIService(); - const result = { curl: 'wget -O - https://n8n.io' }; - expect(() => aiService.validateCurl(result)).toThrow(ApplicationError); - }); - }); -}); diff --git a/packages/cli/test/unit/services/ai/utils/summarizeNodeTypeProperties.test.ts b/packages/cli/test/unit/services/ai/utils/summarizeNodeTypeProperties.test.ts deleted file mode 100644 index 0485c81f30..0000000000 --- a/packages/cli/test/unit/services/ai/utils/summarizeNodeTypeProperties.test.ts +++ /dev/null @@ -1,193 +0,0 @@ -import type { INodeProperties, INodePropertyCollection, INodePropertyOptions } from 'n8n-workflow'; -import { - summarizeNodeTypeProperties, - summarizeOption, - summarizeProperty, -} from '@/services/ai/utils/summarizeNodeTypeProperties'; - -describe('summarizeOption', () => { - it('should return summarized option with value', () => { - const option: INodePropertyOptions = { - name: 'testOption', - value: 'testValue', - }; - - const result = summarizeOption(option); - - expect(result).toEqual({ - name: 'testOption', - value: 'testValue', - }); - }); - - it('should return summarized option with values', () => { - const option: INodePropertyCollection = { - name: 'testOption', - displayName: 'testDisplayName', - values: [ - { - name: 'testName', - default: '', - displayName: 'testDisplayName', - type: 'string', - }, - ], - }; - - const result = summarizeOption(option); - - expect(result).toEqual({ - name: 'testOption', - values: [ - { - name: 'testDisplayName', - type: 'string', - }, - ], - }); - }); - - it('should return summarized property', () => { - const option: INodeProperties = { - name: 'testName', - default: '', - displayName: 'testDisplayName', - type: 'string', - }; - - const result = summarizeOption(option); - - expect(result).toEqual({ - name: 'testDisplayName', - type: 'string', - }); - }); -}); - -describe('summarizeProperty', () => { - it('should return summarized property with displayOptions', () => { - const property: INodeProperties = { - default: '', - name: 'testName', - displayName: 'testDisplayName', - type: 'string', - displayOptions: { - show: { - testOption: ['testValue'], - }, - }, - }; - - const result = summarizeProperty(property); - - expect(result).toEqual({ - name: 'testDisplayName', - type: 'string', - displayOptions: { - show: { - testOption: ['testValue'], - }, - }, - }); - }); - - it('should return summarized property with options', () => { - const property: INodeProperties = { - name: 'testName', - displayName: 'testDisplayName', - default: '', - type: 'string', - options: [ - { - name: 'testOption', - value: 'testValue', - }, - ], - }; - - const result = summarizeProperty(property); - - expect(result).toEqual({ - name: 'testDisplayName', - type: 'string', - options: [ - { - name: 'testOption', - value: 'testValue', - }, - ], - }); - }); - - it('should return summarized property without displayOptions and options', () => { - const property: INodeProperties = { - name: 'testName', - default: '', - displayName: 'testDisplayName', - type: 'string', - }; - - const result = summarizeProperty(property); - - expect(result).toEqual({ - name: 'testDisplayName', - type: 'string', - }); - }); -}); - -describe('summarizeNodeTypeProperties', () => { - it('should return summarized properties', () => { - const properties: INodeProperties[] = [ - { - name: 'testName1', - default: '', - displayName: 'testDisplayName1', - type: 'string', - options: [ - { - name: 'testOption1', - value: 'testValue1', - }, - ], - }, - { - name: 'testName2', - default: '', - displayName: 'testDisplayName2', - type: 'number', - options: [ - { - name: 'testOption2', - value: 'testValue2', - }, - ], - }, - ]; - - const result = summarizeNodeTypeProperties(properties); - - expect(result).toEqual([ - { - name: 'testDisplayName1', - type: 'string', - options: [ - { - name: 'testOption1', - value: 'testValue1', - }, - ], - }, - { - name: 'testDisplayName2', - type: 'number', - options: [ - { - name: 'testOption2', - value: 'testValue2', - }, - ], - }, - ]); - }); -}); diff --git a/packages/editor-ui/src/App.vue b/packages/editor-ui/src/App.vue index 91884e8c53..bb29530e52 100644 --- a/packages/editor-ui/src/App.vue +++ b/packages/editor-ui/src/App.vue @@ -26,9 +26,6 @@ -
- -
@@ -60,8 +57,6 @@ import { useUsageStore } from '@/stores/usage.store'; import { useUsersStore } from '@/stores/users.store'; import { useHistoryHelper } from '@/composables/useHistoryHelper'; import { useRoute } from 'vue-router'; -import { useAIStore } from './stores/ai.store'; -import AIAssistantChat from './components/AIAssistantChat/AIAssistantChat.vue'; export default defineComponent({ name: 'App', @@ -70,7 +65,6 @@ export default defineComponent({ LoadingView, Telemetry, Modals, - AIAssistantChat, }, setup() { return { @@ -91,7 +85,6 @@ export default defineComponent({ useSourceControlStore, useCloudPlanStore, useUsageStore, - useAIStore, ), defaultLocale(): string { return this.rootStore.defaultLocale; @@ -134,10 +127,10 @@ export default defineComponent({ .container { display: grid; grid-template-areas: - 'banners banners banners' - 'sidebar header chat' - 'sidebar content chat'; - grid-auto-columns: fit-content($sidebar-expanded-width) 1fr fit-content($chat-width); + 'banners banners' + 'sidebar header' + 'sidebar content'; + grid-auto-columns: fit-content($sidebar-expanded-width) 1fr; grid-template-rows: auto fit-content($header-height) 1fr; height: 100vh; } @@ -171,15 +164,4 @@ export default defineComponent({ height: 100%; z-index: 999; } -.chat { - grid-area: chat; - z-index: 999; - height: 100%; - width: 0; - transition: all 0.2s ease-in-out; - - &.open { - width: $chat-width; - } -} diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index 0f986ab947..51bca44e14 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -1856,10 +1856,6 @@ export type NewConnectionInfo = { endpointUuid?: string; }; -export type AIAssistantConnectionInfo = NewConnectionInfo & { - stepName?: string; -}; - export type EnterpriseEditionFeatureKey = | 'AdvancedExecutionFilters' | 'Sharing' diff --git a/packages/editor-ui/src/__tests__/defaults.ts b/packages/editor-ui/src/__tests__/defaults.ts index ec67a2517f..950409d78a 100644 --- a/packages/editor-ui/src/__tests__/defaults.ts +++ b/packages/editor-ui/src/__tests__/defaults.ts @@ -114,10 +114,6 @@ export const defaultSettings: IN8nUISettings = { }, ai: { enabled: false, - provider: '', - features: { - generateCurl: false, - }, }, workflowHistory: { pruneTime: 0, diff --git a/packages/editor-ui/src/api/ai.ts b/packages/editor-ui/src/api/ai.ts index ed08cd4128..b7182b6e9b 100644 --- a/packages/editor-ui/src/api/ai.ts +++ b/packages/editor-ui/src/api/ai.ts @@ -2,16 +2,6 @@ import type { IRestApiContext, Schema } from '@/Interface'; import { makeRestApiRequest } from '@/utils/apiUtils'; import type { IDataObject } from 'n8n-workflow'; -export interface GenerateCurlPayload { - service: string; - request: string; -} - -export interface GenerateCurlResponse { - curl: string; - metadata: object; -} - export async function generateCodeForPrompt( ctx: IRestApiContext, { @@ -38,15 +28,3 @@ export async function generateCodeForPrompt( n8nVersion, } as IDataObject); } - -export const generateCurl = async ( - context: IRestApiContext, - payload: GenerateCurlPayload, -): Promise => { - return await makeRestApiRequest( - context, - 'POST', - '/ai/generate-curl', - payload as unknown as IDataObject, - ); -}; diff --git a/packages/editor-ui/src/components/AIAssistantChat/AIAssistantChat.vue b/packages/editor-ui/src/components/AIAssistantChat/AIAssistantChat.vue deleted file mode 100644 index 810dbd5c92..0000000000 --- a/packages/editor-ui/src/components/AIAssistantChat/AIAssistantChat.vue +++ /dev/null @@ -1,225 +0,0 @@ - - - - - diff --git a/packages/editor-ui/src/components/AIAssistantChat/NextStepPopup.vue b/packages/editor-ui/src/components/AIAssistantChat/NextStepPopup.vue deleted file mode 100644 index e3baafc4c7..0000000000 --- a/packages/editor-ui/src/components/AIAssistantChat/NextStepPopup.vue +++ /dev/null @@ -1,148 +0,0 @@ - - - - - diff --git a/packages/editor-ui/src/components/AIAssistantChat/QuickReplies.vue b/packages/editor-ui/src/components/AIAssistantChat/QuickReplies.vue deleted file mode 100644 index 77a0519cd4..0000000000 --- a/packages/editor-ui/src/components/AIAssistantChat/QuickReplies.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - - - diff --git a/packages/editor-ui/src/components/GenerateCurlModal.vue b/packages/editor-ui/src/components/GenerateCurlModal.vue deleted file mode 100644 index ef590ea4ca..0000000000 --- a/packages/editor-ui/src/components/GenerateCurlModal.vue +++ /dev/null @@ -1,216 +0,0 @@ - - - - - diff --git a/packages/editor-ui/src/components/ImportCurlParameter.vue b/packages/editor-ui/src/components/ImportCurlParameter.vue index 22ebd2f33e..548ed55cc6 100644 --- a/packages/editor-ui/src/components/ImportCurlParameter.vue +++ b/packages/editor-ui/src/components/ImportCurlParameter.vue @@ -1,22 +1,16 @@ diff --git a/packages/editor-ui/src/components/Modals.vue b/packages/editor-ui/src/components/Modals.vue index 046572c5e5..8acf73be79 100644 --- a/packages/editor-ui/src/components/Modals.vue +++ b/packages/editor-ui/src/components/Modals.vue @@ -29,7 +29,6 @@ import { MFA_SETUP_MODAL_KEY, WORKFLOW_HISTORY_VERSION_RESTORE, SETUP_CREDENTIALS_MODAL_KEY, - GENERATE_CURL_MODAL_KEY, PROJECT_MOVE_RESOURCE_MODAL, PROJECT_MOVE_RESOURCE_CONFIRM_MODAL, } from '@/constants'; @@ -55,7 +54,6 @@ import WorkflowSettings from '@/components/WorkflowSettings.vue'; import DeleteUserModal from '@/components/DeleteUserModal.vue'; import ActivationModal from '@/components/ActivationModal.vue'; import ImportCurlModal from '@/components/ImportCurlModal.vue'; -import GenerateCurlModal from '@/components/GenerateCurlModal.vue'; import MfaSetupModal from '@/components/MfaSetupModal.vue'; import WorkflowShareModal from '@/components/WorkflowShareModal.ee.vue'; import EventDestinationSettingsModal from '@/components/SettingsLogStreaming/EventDestinationSettingsModal.ee.vue'; @@ -166,10 +164,6 @@ import ProjectMoveResourceConfirmModal from '@/components/Projects/ProjectMoveRe - - - -