first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,411 @@
import type { INodeProperties } from 'n8n-workflow';
export const agentOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['agent'],
},
},
options: [
{
name: 'Delete',
value: 'delete',
description: 'Delete an agent by ID',
action: 'Delete an agent',
},
{
name: 'Get',
value: 'get',
description: 'Get an agent by ID',
action: 'Get an agent',
},
{
name: 'Get Many',
value: 'getAll',
description: "Get many agents of the current user's organization",
action: 'Get many agents',
},
{
name: 'Get Output',
value: 'getOutput',
description: 'Get the output of the most recent container of an agent',
action: 'Get the output of an agent',
},
{
name: 'Launch',
value: 'launch',
description: 'Add an agent to the launch queue',
action: 'Add an agent to the launch queue',
},
],
default: 'launch',
},
];
export const agentFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */
/* agent:delete */
/* -------------------------------------------------------------------------- */
{
displayName: 'Agent Name or ID',
name: 'agentId',
type: 'options',
description:
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
typeOptions: {
loadOptionsMethod: 'getAgents',
},
required: true,
displayOptions: {
show: {
operation: ['delete'],
resource: ['agent'],
},
},
default: '',
},
/* -------------------------------------------------------------------------- */
/* agent:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Agent ID',
name: 'agentId',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['get'],
resource: ['agent'],
},
},
default: '',
},
/* -------------------------------------------------------------------------- */
/* agent:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['agent'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['agent'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
maxValue: 50,
},
default: 25,
description: 'Max number of results to return',
},
/* -------------------------------------------------------------------------- */
/* agent:getOutput */
/* -------------------------------------------------------------------------- */
{
displayName: 'Agent Name or ID',
name: 'agentId',
type: 'options',
description:
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
typeOptions: {
loadOptionsMethod: 'getAgents',
},
required: true,
displayOptions: {
show: {
operation: ['getOutput'],
resource: ['agent'],
},
},
default: '',
},
{
displayName: 'Resolve Data',
name: 'resolveData',
type: 'boolean',
default: true,
displayOptions: {
show: {
operation: ['getOutput'],
resource: ['agent'],
},
},
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
description:
'By default the outpout is presented as string. If this option gets activated, it will resolve the data automatically.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
resource: ['agent'],
operation: ['getOutput'],
},
},
default: {},
options: [
{
displayName: 'Prev Container ID',
name: 'prevContainerId',
type: 'string',
default: '',
description:
'If set, the output will be retrieved from the container after the specified previous container ID',
},
{
displayName: 'Prev Status',
name: 'prevStatus',
type: 'options',
options: [
{
name: 'Finished',
value: 'finished',
},
{
name: 'Launch Error',
value: 'lauch error',
},
{
name: 'Never Launched',
value: 'never launched',
},
{
name: 'Running',
value: 'running',
},
{
name: 'Starting',
value: 'starting',
},
{
name: 'Unknown',
value: 'unknown',
},
],
default: '',
description: 'If set, allows to define which status was previously retrieved on user-side',
},
{
displayName: 'Pre Runtime Event Index',
name: 'prevRuntimeEventIndex',
type: 'number',
default: 0,
description:
"If set, the container's runtime events will be returned in the response starting from the provided previous runtime event index",
},
],
},
/* -------------------------------------------------------------------------- */
/* agent:launch */
/* -------------------------------------------------------------------------- */
{
displayName: 'Agent Name or ID',
name: 'agentId',
type: 'options',
description:
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
typeOptions: {
loadOptionsMethod: 'getAgents',
},
required: true,
displayOptions: {
show: {
operation: ['launch'],
resource: ['agent'],
},
},
default: '',
},
{
displayName: 'Resolve Data',
name: 'resolveData',
type: 'boolean',
default: true,
displayOptions: {
show: {
operation: ['launch'],
resource: ['agent'],
},
},
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
description:
'By default the launch just include the container ID. If this option gets activated, it will resolve the data automatically.',
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['launch'],
resource: ['agent'],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
resource: ['agent'],
operation: ['launch'],
},
},
default: {},
options: [
{
displayName: 'Arguments (JSON)',
name: 'argumentsJson',
type: 'json',
displayOptions: {
show: {
'/jsonParameters': [true],
},
},
default: '',
description:
'Agent argument. Can either be a JSON string or a plain object. The argument can be retrieved with buster.argument in the agents script.',
},
{
displayName: 'Arguments',
name: 'argumentsUi',
placeholder: 'Add Argument',
type: 'fixedCollection',
default: {},
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
'/jsonParameters': [false],
},
},
options: [
{
name: 'argumentValues',
displayName: 'Argument',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
description: 'Name of the argument key to add',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
description: 'Value to set for the argument key',
},
],
},
],
},
{
displayName: 'Bonus Argument',
name: 'bonusArgumentUi',
placeholder: 'Add Bonus Argument',
type: 'fixedCollection',
default: {},
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
'/jsonParameters': [false],
},
},
options: [
{
name: 'bonusArgumentValue',
displayName: 'Bonus Argument',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
description: 'Name of the argument key to add',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
description: 'Value to set for the argument key',
},
],
},
],
},
{
displayName: 'Bonus Argument (JSON)',
name: 'bonusArgumentJson',
type: 'string',
displayOptions: {
show: {
'/jsonParameters': [true],
},
},
default: '',
description:
'Agent bonus argument. Can either be a JSON string or a plain object. This bonus argument is single-use, it will only be used for the current launch. If present, it will be merged with the original argument, resulting in an effective argument that can be retrieved with buster.argument in the agents script.',
},
{
displayName: 'Manual Launch',
name: 'manualLaunch',
type: 'boolean',
default: false,
description: 'Whether the agent will be considered as "launched manually"',
},
{
displayName: 'Max Instance Count',
name: 'maxInstanceCount',
type: 'number',
default: 0,
description:
'If set, the agent will only be launched if the number of already running instances is below the specified number',
},
{
displayName: 'Save Argument',
name: 'saveArgument',
type: 'string',
default: '',
description: 'If true, argument will be saved as the default launch options for the agent',
},
],
},
];
@@ -0,0 +1,46 @@
import type {
JsonObject,
IDataObject,
IExecuteFunctions,
ILoadOptionsFunctions,
IHttpRequestMethods,
IRequestOptions,
} from 'n8n-workflow';
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
export async function phantombusterApiRequest(
this: IExecuteFunctions | ILoadOptionsFunctions,
method: IHttpRequestMethods,
path: string,
body: any = {},
qs: IDataObject = {},
_option = {},
): Promise<any> {
const options: IRequestOptions = {
headers: {},
method,
body,
qs,
uri: `https://api.phantombuster.com/api/v2${path}`,
json: true,
};
try {
if (Object.keys(body as IDataObject).length === 0) {
delete options.body;
}
return await this.helpers.requestWithAuthentication.call(this, 'phantombusterApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
}
export function validateJSON(self: IExecuteFunctions, json: string | undefined, name: string) {
let result;
try {
result = JSON.parse(json!);
} catch (exception) {
throw new NodeOperationError(self.getNode(), `${name} must provide a valid JSON`);
}
return result;
}
@@ -0,0 +1,18 @@
{
"node": "n8n-nodes-base.phantombuster",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Sales", "Marketing"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/phantombuster/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.phantombuster/"
}
]
}
}
@@ -0,0 +1,285 @@
import {
type IExecuteFunctions,
type IDataObject,
type ILoadOptionsFunctions,
type INodeExecutionData,
type INodePropertyOptions,
type INodeType,
type INodeTypeDescription,
NodeConnectionTypes,
} from 'n8n-workflow';
import { agentFields, agentOperations } from './AgentDescription';
import { phantombusterApiRequest, validateJSON } from './GenericFunctions';
// import {
// sentenceCase,
// } from 'change-case';
export class Phantombuster implements INodeType {
description: INodeTypeDescription = {
displayName: 'Phantombuster',
name: 'phantombuster',
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
icon: 'file:phantombuster.png',
group: ['input'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Phantombuster API',
defaults: {
name: 'Phantombuster',
},
builderHint: {
message:
'Recommended for scraping LinkedIn profiles and social media for leads, and company data. Use with AI Agent for lead generation workflows.',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'phantombusterApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Agent',
value: 'agent',
},
],
default: 'agent',
},
...agentOperations,
...agentFields,
],
};
methods = {
loadOptions: {
async getAgents(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const responseData = await phantombusterApiRequest.call(this, 'GET', '/agents/fetch-all');
for (const item of responseData) {
returnData.push({
name: item.name,
value: item.id,
});
}
return returnData;
},
// Get all the arguments to display them to user so that they can
// select them easily
// async getArguments(
// this: ILoadOptionsFunctions,
// ): Promise<INodePropertyOptions[]> {
// const returnData: INodePropertyOptions[] = [];
// const agentId = this.getCurrentNodeParameter('agentId') as string;
// const { argument } = await phantombusterApiRequest.call(
// this,
// 'GET',
// '/agents/fetch',
// {},
// { id: agentId },
// );
// for (const key of Object.keys(JSON.parse(argument))) {
// returnData.push({
// name: sentenceCase(key),
// value: key,
// });
// }
// return returnData;
// },
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
const length = items.length;
const qs: IDataObject = {};
let responseData;
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < length; i++) {
try {
if (resource === 'agent') {
//https://hub.phantombuster.com/reference#post_agents-delete-1
if (operation === 'delete') {
const agentId = this.getNodeParameter('agentId', i) as string;
responseData = await phantombusterApiRequest.call(this, 'POST', '/agents/delete', {
id: agentId,
});
responseData = { success: true };
}
//https://hub.phantombuster.com/reference#get_agents-fetch-1
if (operation === 'get') {
const agentId = this.getNodeParameter('agentId', i) as string;
responseData = await phantombusterApiRequest.call(
this,
'GET',
'/agents/fetch',
{},
{ id: agentId },
);
}
//https://hub.phantombuster.com/reference#get_agents-fetch-output-1
if (operation === 'getOutput') {
const agentId = this.getNodeParameter('agentId', i) as string;
const resolveData = this.getNodeParameter('resolveData', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
qs.id = agentId;
responseData = await phantombusterApiRequest.call(
this,
'GET',
'/agents/fetch-output',
{},
qs,
);
if (resolveData) {
const { resultObject } = await phantombusterApiRequest.call(
this,
'GET',
'/containers/fetch-result-object',
{},
{ id: responseData.containerId },
);
if (resultObject === null) {
responseData = {};
} else {
responseData = JSON.parse(resultObject as string);
}
}
}
//https://api.phantombuster.com/api/v2/agents/fetch-all
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i);
responseData = await phantombusterApiRequest.call(this, 'GET', '/agents/fetch-all');
if (!returnAll) {
const limit = this.getNodeParameter('limit', 0);
responseData = responseData.splice(0, limit);
}
}
//https://hub.phantombuster.com/reference#post_agents-launch-1
if (operation === 'launch') {
const agentId = this.getNodeParameter('agentId', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i);
const resolveData = this.getNodeParameter('resolveData', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
const body: IDataObject = {
id: agentId,
};
if (jsonParameters) {
if (additionalFields.argumentsJson) {
body.arguments = validateJSON(
this,
additionalFields.argumentsJson as string,
'Arguments',
);
delete additionalFields.argumentsJson;
}
if (additionalFields.bonusArgumentJson) {
body.bonusArgument = validateJSON(
this,
additionalFields.bonusArgumentJson as string,
'Bonus Argument',
);
delete additionalFields.bonusArgumentJson;
}
} else {
const argumentParameters =
((additionalFields.argumentsUi as IDataObject)?.argumentValues as IDataObject[]) ||
[];
const argumentsObj = argumentParameters.reduce((object, currentValue) => {
object[currentValue.key as string] = currentValue.value;
return object;
}, {});
// Only set arguments if not empty as per API requirements
if (Object.keys(argumentsObj).length > 0) {
body.arguments = argumentsObj;
}
delete additionalFields.argumentsUi;
const bonusParameters =
((additionalFields.bonusArgumentUi as IDataObject)
?.bonusArgumentValue as IDataObject[]) || [];
const bonusArgumentObj = bonusParameters.reduce((object, currentValue) => {
object[currentValue.key as string] = currentValue.value;
return object;
}, {});
// Only set bonusArgument if not empty as per API requirements
if (Object.keys(bonusArgumentObj).length > 0) {
body.bonusArgument = bonusArgumentObj;
}
delete additionalFields.bonusArgumentUi;
}
Object.assign(body, additionalFields);
responseData = await phantombusterApiRequest.call(this, 'POST', '/agents/launch', body);
if (resolveData) {
responseData = await phantombusterApiRequest.call(
this,
'GET',
'/containers/fetch',
{},
{ id: responseData.containerId },
);
}
}
}
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData: { item: i } },
);
returnData.push(...executionData);
} catch (error) {
if (this.continueOnFail()) {
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData: { item: i } },
);
returnData.push(...executionData);
continue;
}
throw error;
}
}
return [returnData];
}
}
@@ -0,0 +1,89 @@
{
"type": "object",
"properties": {
"argument": {
"type": "string"
},
"branch": {
"type": "string"
},
"code": {
"type": "null"
},
"environment": {
"type": "string"
},
"fileMgmt": {
"type": "string"
},
"id": {
"type": "string"
},
"lastEndType": {
"type": "string"
},
"launchType": {
"type": "string"
},
"maxParallelism": {
"type": "integer"
},
"name": {
"type": "string"
},
"nbLaunches": {
"type": "integer"
},
"notifications": {
"type": "object",
"properties": {
"mailAutomaticExitError": {
"type": "boolean"
},
"mailAutomaticExitSuccess": {
"type": "boolean"
},
"mailAutomaticLaunchError": {
"type": "boolean"
},
"mailAutomaticTimeError": {
"type": "boolean"
},
"mailManualExitError": {
"type": "boolean"
},
"mailManualExitSuccess": {
"type": "boolean"
},
"mailManualLaunchError": {
"type": "boolean"
},
"mailManualTimeError": {
"type": "boolean"
}
}
},
"orgS3Folder": {
"type": "string"
},
"s3Folder": {
"type": "string"
},
"script": {
"type": "string"
},
"scriptId": {
"type": "string"
},
"scriptOrgName": {
"type": "string"
},
"updatedAt": {
"type": "integer"
},
"wasSetupValidWhenSubmittedByTheFrontend": {
"type": "boolean"
}
},
"version": 1
}
@@ -0,0 +1,12 @@
{
"type": "object",
"properties": {
"profileUrl": {
"type": "string"
},
"timestamp": {
"type": "string"
}
},
"version": 5
}
@@ -0,0 +1,24 @@
{
"type": "object",
"properties": {
"createdAt": {
"type": "integer"
},
"id": {
"type": "string"
},
"launchedAt": {
"type": "integer"
},
"launchType": {
"type": "string"
},
"retryNumber": {
"type": "integer"
},
"status": {
"type": "string"
}
},
"version": 1
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

@@ -0,0 +1,95 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import nock from 'nock';
describe('Phantombuster Node', () => {
const credentials = {
phantombusterApi: {
apiKey: 'test-api-key',
},
};
describe('Launch Agent Without Arguments', () => {
beforeAll(() => {
const mock = nock('https://api.phantombuster.com');
mock
.post('/api/v2/agents/launch', (body) => {
return body.id === 'test-agent-123' && !body.arguments && !body.bonusArgument;
})
.reply(200, { containerId: 'container-456' });
});
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['launch-without-arguments.workflow.json'],
});
});
describe('Launch Agent With Arguments No Bonus', () => {
beforeAll(() => {
const mock = nock('https://api.phantombuster.com');
mock
.post('/api/v2/agents/launch', (body) => {
return (
body.id === 'test-agent-123' &&
body.arguments &&
body.arguments.testKey === 'testValue' &&
!body.bonusArgument
);
})
.reply(200, { containerId: 'container-456' });
});
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['launch-with-arguments-no-bonus.workflow.json'],
});
});
describe('Launch Agent With Bonus Arguments', () => {
beforeAll(() => {
const mock = nock('https://api.phantombuster.com');
mock
.post('/api/v2/agents/launch', (body) => {
return (
body.id === 'test-agent-123' &&
body.arguments &&
body.arguments.testKey === 'testValue' &&
body.bonusArgument &&
body.bonusArgument.bonusKey === 'bonusValue'
);
})
.reply(200, { containerId: 'container-456' });
});
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['launch-with-bonus-arguments.workflow.json'],
});
});
describe('Launch Agent With JSON Arguments', () => {
beforeAll(() => {
const mock = nock('https://api.phantombuster.com');
mock
.post('/api/v2/agents/launch', (body) => {
return (
body.id === 'test-agent-123' &&
body.arguments &&
body.arguments.complexKey === 'complexValue' &&
body.arguments.nestedObject &&
body.arguments.nestedObject.nested === 'value'
);
})
.reply(200, { containerId: 'container-456' });
});
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['launch-with-json-arguments.workflow.json'],
});
});
});
@@ -0,0 +1,69 @@
{
"name": "Phantombuster Launch With Arguments No Bonus Test",
"nodes": [
{
"parameters": {},
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "When clicking 'Execute Workflow'",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0]
},
{
"parameters": {
"resource": "agent",
"operation": "launch",
"agentId": "test-agent-123",
"jsonParameters": false,
"resolveData": false,
"additionalFields": {
"argumentsUi": {
"argumentValues": [
{
"key": "testKey",
"value": "testValue"
}
]
}
}
},
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Phantombuster",
"type": "n8n-nodes-base.phantombuster",
"typeVersion": 1,
"position": [220, 0],
"credentials": {
"phantombusterApi": {
"id": "test-cred-id",
"name": "Phantombuster API"
}
}
}
],
"pinData": {
"Phantombuster": [
{
"json": {
"containerId": "container-456"
}
}
]
},
"connections": {
"When clicking 'Execute Workflow'": {
"main": [
[
{
"node": "Phantombuster",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
@@ -0,0 +1,77 @@
{
"name": "Phantombuster Launch With Bonus Arguments Test",
"nodes": [
{
"parameters": {},
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "When clicking 'Execute Workflow'",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0]
},
{
"parameters": {
"resource": "agent",
"operation": "launch",
"agentId": "test-agent-123",
"jsonParameters": false,
"resolveData": false,
"additionalFields": {
"argumentsUi": {
"argumentValues": [
{
"key": "testKey",
"value": "testValue"
}
]
},
"bonusArgumentUi": {
"bonusArgumentValue": [
{
"key": "bonusKey",
"value": "bonusValue"
}
]
}
}
},
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Phantombuster",
"type": "n8n-nodes-base.phantombuster",
"typeVersion": 1,
"position": [220, 0],
"credentials": {
"phantombusterApi": {
"id": "test-cred-id",
"name": "Phantombuster API"
}
}
}
],
"pinData": {
"Phantombuster": [
{
"json": {
"containerId": "container-456"
}
}
]
},
"connections": {
"When clicking 'Execute Workflow'": {
"main": [
[
{
"node": "Phantombuster",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
@@ -0,0 +1,62 @@
{
"name": "Phantombuster Launch With JSON Arguments Test",
"nodes": [
{
"parameters": {},
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "When clicking 'Execute Workflow'",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0]
},
{
"parameters": {
"resource": "agent",
"operation": "launch",
"agentId": "test-agent-123",
"jsonParameters": true,
"resolveData": false,
"additionalFields": {
"argumentsJson": "{\"complexKey\":\"complexValue\",\"nestedObject\":{\"nested\":\"value\"}}"
}
},
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Phantombuster",
"type": "n8n-nodes-base.phantombuster",
"typeVersion": 1,
"position": [220, 0],
"credentials": {
"phantombusterApi": {
"id": "test-cred-id",
"name": "Phantombuster API"
}
}
}
],
"pinData": {
"Phantombuster": [
{
"json": {
"containerId": "container-456"
}
}
]
},
"connections": {
"When clicking 'Execute Workflow'": {
"main": [
[
{
"node": "Phantombuster",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
@@ -0,0 +1,59 @@
{
"name": "Phantombuster Launch Without Arguments Test",
"nodes": [
{
"parameters": {},
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "When clicking 'Execute Workflow'",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0]
},
{
"parameters": {
"resource": "agent",
"operation": "launch",
"agentId": "test-agent-123",
"jsonParameters": false,
"resolveData": false
},
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Phantombuster",
"type": "n8n-nodes-base.phantombuster",
"typeVersion": 1,
"position": [220, 0],
"credentials": {
"phantombusterApi": {
"id": "test-cred-id",
"name": "Phantombuster API"
}
}
}
],
"pinData": {
"Phantombuster": [
{
"json": {
"containerId": "container-456"
}
}
]
},
"connections": {
"When clicking 'Execute Workflow'": {
"main": [
[
{
"node": "Phantombuster",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}