MichaelThe modern B2B landscape is a digital archipelago. Marketing has HubSpot, Sales has Salesforce,...
The modern B2B landscape is a digital archipelago. Marketing has HubSpot, Sales has Salesforce, Engineering has Jira, and Support has Zendesk. This SaaS sprawl is great for departmental productivity, but it creates data silos that cripple cross-functional workflows. As developers, we're the ones tasked with building the bridges.
But just connecting App A to App B with a quick script isn't enough. That approach leads to a brittle, tangled mess of bespoke integrations that are impossible to maintain. To truly connect a B2B tech stack, you need to stop thinking like a plumber and start thinking like an architect. You need to architect flow.
Yes, platforms like Zapier and Make.com are fantastic. They've democratized automation and are perfect for simple, linear tasks. "When this, do that." But as soon as your business logic gets interesting, they hit a wall.
Consider these common B2B scenarios:
This is where no-code solutions become cumbersome or prohibitively expensive. This is where developers shine, by building custom, resilient, and scalable integration logic.
Before you write a single line of code, internalize these architectural principles. They're the foundation of any robust integration strategy.
Treat the APIs of your SaaS tools not as an afterthought, but as first-class products. Before you start building, do your homework:
Account versus how HubSpot represents a Company?Imagine a network glitch causes your function to fire twice. If that function is "Create Customer," you've just created a duplicate. An idempotent API ensures that making the same request multiple times produces the same result as making it once. When building your own endpoints or calling others, always ask: "What happens if this runs twice?" If the answer is bad, you need to build in idempotency checks, often using a unique key from the source event.
Constantly polling an API for changes (GET /deals every 5 minutes) is inefficient and a great way to hit your rate limits. A far better approach is to use webhooks.
With a webhook, the SaaS application tells you when something interesting happens by sending a POST request to an endpoint you control. This is the heart of a modern, responsive, and efficient integration system.
Let's make this concrete. Goal: When a deal in our CRM is marked "Closed Won," automatically create a new project in Asana to kick off the client onboarding process.
In your CRM (e.g., HubSpot, Salesforce), you'll navigate to the webhooks or API settings. You'll subscribe to deal updates and provide the URL of your integration service. When a deal stage changes, the CRM will send a payload to your URL that looks something like this:
[
{
"objectId": 123456789,
"propertyName": "dealstage",
"propertyValue": "closedwon",
"changeSource": "CRM_UI",
"portalId": 98765,
"appId": 54321,
"occurredAt": 1678886400000
}
]
This is where our custom logic lives. We can build a simple Node.js and Express server to listen for this webhook, parse the payload, and then make a corresponding API call to Asana.
Here's a simplified example of what that server might look like:
import express from 'express';
import fetch from 'node-fetch'; // Or use native fetch in Node.js 18+
const app = express();
app.use(express.json());
// Store secrets in environment variables, NOT in code!
const ASANA_API_KEY = process.env.ASANA_API_KEY;
const ASANA_WORKSPACE_GID = process.env.ASANA_WORKSPACE_GID;
const ASANA_TEAM_GID = process.env.ASANA_TEAM_GID;
// Our webhook listener endpoint
app.post('/webhooks/hubspot-deal-closed', async (req, res) => {
console.log('Received HubSpot webhook:', req.body);
const dealEvent = req.body[0]; // HubSpot sends an array of events
// Filter for the specific event we care about
if (dealEvent.propertyName === 'dealstage' && dealEvent.propertyValue === 'closedwon') {
const dealId = dealEvent.objectId;
try {
// In a real app, you'd probably use the dealId to fetch more
// details from the HubSpot API (like deal name, value, etc.)
const dealName = `Onboarding Project for Deal #${dealId}`;
console.log(`Creating Asana project for: ${dealName}`);
const response = await fetch('https://app.asana.com/api/1.0/projects', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${ASANA_API_KEY}`,
},
body: JSON.stringify({
data: {
name: dealName,
team: ASANA_TEAM_GID,
workspace: ASANA_WORKSPACE_GID,
notes: `Auto-created from CRM deal ${dealId}.`
},
}),
});
if (!response.ok) {
// The Asana API returned an error
const errorBody = await response.text();
throw new Error(`Asana API Error: ${response.status} ${errorBody}`);
}
const asanaProject = await response.json();
console.log('Successfully created Asana project:', asanaProject.data.gid);
res.status(200).send({ message: 'Project created successfully.' });
} catch (error) {
console.error('Failed to process webhook:', error);
// Let the caller know something went wrong
res.status(500).send({ message: 'Internal Server Error' });
}
} else {
// Not the event we're interested in, but acknowledge receipt
res.status(200).send({ message: 'Event received, no action taken.' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Integration server listening on port ${PORT}`));
What happens if the Asana API is down when our webhook fires? A simple try...catch is a good start, but for enterprise application integration, you need more.
As you build more of these workflows, you'll notice patterns. You'll be writing the same authentication, error handling, and logging code over and over. This is the point to level up from ad-hoc scripts to a dedicated integration layer.
This could be a standalone microservice within your architecture that handles all third-party API interactions. Its job is to expose a clean, internal API for the rest of your system and manage the messy reality of the outside world. This approach centralizes credentials, logging, and monitoring, making your integrations easier to manage and scale.
Effective SaaS integration is more than just passing data between two points. It’s about deeply understanding the business process you're trying to automate and building a resilient, scalable system to support it.
By adopting an architect's mindset—focusing on APIs, event-driven patterns, and robust error handling—you can transform a disjointed collection of applications into a cohesive, automated powerhouse that gives your business a competitive edge.
Originally published at https://getmichaelai.com/blog/the-b2b-guide-to-saas-integration-connecting-your-tech-stack