Common errors
This guide covers advanced usage patterns for the Linked API SDK, including custom workflow execution, state management, and complex automation scenarios. These techniques help you build more efficient and robust LinkedIn automation applications.
Custom workflow execution
For complex multi-step operations, custom workflows provide better performance, atomicity, and error handling by executing all steps server-side in a single workflow execution. This approach is more efficient than chaining multiple SDK methods. Consult the Account API documentation and Data API documentation for complete API references and advanced workflow patterns.
When to use custom workflows
- Multi-step data collection: Search for companies, then retrieve employees and decision makers for each.
- Bulk outreach campaigns: Search for prospects, then send connection requests to filtered results.
- Complex data analysis: Gather company data, analyze employee profiles, and perform calculations.
- High-volume operations: Any workflow processing hundreds or thousands of items.
Account API custom workflows
// Complex prospecting workflow
const prospectingWorkflow = await linkedapi.account.executeCustomWorkflow({
actionType: "st.searchCompanies",
term: "AI startup",
filter: {
locations: ["San Francisco", "New York"],
sizes: ["11-50", "51-200"],
industries: ["Software Development", "Artificial Intelligence"]
},
limit: 10,
then: {
actionType: "st.doForCompanies",
then: {
actionType: "st.openCompanyPage",
basicInfo: true,
then: [
{
actionType: "st.retrieveCompanyEmployees",
limit: 10,
filter: {
positions: ["CEO", "CTO", "VP", "Director"],
},
then: {
actionType: "st.doForPeople",
then: {
actionType: "st.sendConnectionRequest",
message: "Hi! I'm interested in discussing AI innovations with industry leaders.",
email: "john@example.com"
}
}
},
{
actionType: "st.retrieveCompanyDMs",
limit: 3
}
]
}
}
});
const result = await prospectingWorkflow.result();
console.log("Prospecting workflow completed:", result);
# Python SDK is coming soon!
#
# You can always use Account API or Data API directly
# https://linkedapi.io/docs/
// Go SDK is coming soon!
//
// You can always use Account API or Data API directly
// https://linkedapi.io/docs/
Data API custom workflows
// Comprehensive market research workflow
const marketResearchWorkflow = await linkedapi.data.executeCustomWorkflow({
actionType: "searchCompanies",
term: "fintech",
filter: {
locations: ["London", "Berlin", "Amsterdam"],
sizes: ["201-500", "501-1000", "1001-5000"],
annualRevenue: {
min: "10",
max: "500"
}
},
limit: 10,
then: {
actionType: "doForCompanies",
then: {
actionType: "openCompanyPage",
basicInfo: true,
then: [
{
actionType: "retrieveCompanyEmployees",
limit: 25,
filter: {
positions: ["Engineer", "Developer", "Technical Lead"]
}
},
{
actionType: "retrieveCompanyPosts",
limit: 10,
since: "2024-06-01"
}
]
}
}
});
const marketData = await marketResearchWorkflow.result();
console.log("Market research completed:", marketData);
# Python SDK is coming soon!
#
# You can always use Account API or Data API directly
# https://linkedapi.io/docs/
// Go SDK is coming soon!
//
// You can always use Account API or Data API directly
// https://linkedapi.io/docs/
Workflow persistence and state management
Linked API workflows are designed to be resilient and stateful. Each workflow receives a unique workflowId
that persists even if your application restarts or loses connection during execution.
Storing workflow IDs for persistence
import fs from 'fs/promises';
// Database interface for workflow persistence
class WorkflowManager {
constructor(filePath = './workflows.json') {
this.filePath = filePath;
}
async saveWorkflow(workflowId, metadata) {
let workflows = {};
try {
const data = await fs.readFile(this.filePath, 'utf8');
workflows = JSON.parse(data);
} catch (error) {
// File doesn't exist or is empty
}
workflows[workflowId] = {
...metadata,
createdAt: new Date().toISOString(),
status: 'running'
};
await fs.writeFile(this.filePath, JSON.stringify(workflows, null, 2));
}
async getWorkflow(workflowId) {
try {
const data = await fs.readFile(this.filePath, 'utf8');
const workflows = JSON.parse(data);
return workflows[workflowId] || null;
} catch (error) {
return null;
}
}
async updateWorkflowStatus(workflowId, status, result = null) {
const data = await fs.readFile(this.filePath, 'utf8');
const workflows = JSON.parse(data);
if (workflows[workflowId]) {
workflows[workflowId].status = status;
workflows[workflowId].completedAt = new Date().toISOString();
if (result) workflows[workflowId].result = result;
await fs.writeFile(this.filePath, JSON.stringify(workflows, null, 2));
}
}
async getPendingWorkflows() {
try {
const data = await fs.readFile(this.filePath, 'utf8');
const workflows = JSON.parse(data);
return Object.entries(workflows)
.filter(([, workflow]) => workflow.status === 'running')
.map(([id, workflow]) => ({ id, ...workflow }));
} catch (error) {
return [];
}
}
}
// Usage example
const workflowManager = new WorkflowManager();
async function startLongRunningWorkflow() {
const workflow = await linkedapi.account.searchCompanies({
term: "tech startup",
filter: { locations: ["Silicon Valley"] },
limit: 100
});
// Save workflow ID immediately
await workflowManager.saveWorkflow(workflow.workflowId, {
type: 'account.searchCompanies',
term: 'tech startup',
description: 'Large scale company search for lead generation'
});
console.log(`Workflow ${workflow.workflowId} started and saved`);
try {
const result = await workflow.result();
await workflowManager.updateWorkflowStatus(
workflow.workflowId,
'completed',
result
);
console.log('Workflow completed successfully');
} catch (error) {
await workflowManager.updateWorkflowStatus(
workflow.workflowId,
'failed',
{ error: error.message }
);
console.error('Workflow failed:', error);
}
}
# Python SDK is coming soon!
#
# You can always use Account API or Data API directly
# https://linkedapi.io/docs/
// Go SDK is coming soon!
//
// You can always use Account API or Data API directly
// https://linkedapi.io/docs/
Recovering interrupted workflows
// Recovery function to resume interrupted workflows
async function recoverPendingWorkflows() {
const pendingWorkflows = await workflowManager.getPendingWorkflows();
console.log(`Found ${pendingWorkflows.length} pending workflows`);
for (const workflow of pendingWorkflows) {
try {
console.log(`Recovering workflow ${workflow.id} (${workflow.type})`);
// Check workflow status using the appropriate API
let result;
if (workflow.type?.includes('account.')) {
result = await linkedapi.account.getWorkflowResult(workflow.id);
} else {
result = await linkedapi.data.getWorkflowResult(workflow.id);
}
if (result.completion) {
// Workflow completed while we were away
await workflowManager.updateWorkflowStatus(
workflow.id,
'completed',
result.completion.data
);
console.log(`Workflow ${workflow.id} recovered - completed`);
// Process the results
await processWorkflowResults(workflow.id, result.completion.data);
} else if (result.error) {
// Workflow failed
await workflowManager.updateWorkflowStatus(
workflow.id,
'failed',
{ error: result.error }
);
console.log(`Workflow ${workflow.id} recovered - failed`);
} else {
// Still running, keep monitoring
console.log(`Workflow ${workflow.id} still running`);
}
} catch (error) {
console.error(`Failed to recover workflow ${workflow.id}:`, error);
await workflowManager.updateWorkflowStatus(
workflow.id,
'failed',
{ error: error.message }
);
}
}
}
// Process completed workflow results
async function processWorkflowResults(workflowId, data) {
console.log(`Processing results for workflow ${workflowId}`);
// Example: Save to database, send notifications, etc.
// This depends on your specific use case
if (Array.isArray(data)) {
console.log(`Processed ${data.length} items from workflow ${workflowId}`);
}
}
// Run recovery on application startup
await recoverPendingWorkflows();
# Python SDK is coming soon!
#
# You can always use Account API or Data API directly
# https://linkedapi.io/docs/
// Go SDK is coming soon!
//
// You can always use Account API or Data API directly
// https://linkedapi.io/docs/
Best practices
- Use custom workflows for complex multi-step operations to improve performance.
- Implement persistent storage for workflow IDs to enable recovery from interruptions.
- Add comprehensive error handling with retry mechanisms.
- Monitor API usage to track performance and optimize workflows.
- Log comprehensively for debugging and monitoring purposes.
- Use environment variables for API tokens and configuration.
- Test thoroughly with small datasets before scaling to production volumes.