What developers build with nodestash
From SaaS backends to AI agents — nodestash provides the CRM infrastructure so you can focus on what makes your product unique.
B2B SaaS Backend
Add CRM functionality to your SaaS product without building a CRM from scratch. Use nodestash as your customer data layer and focus on your core product.
- Store customer data alongside your application data without running a separate CRM
- Auto-create contacts and deals when users sign up or upgrade
- Use custom fields to link CRM records to your internal user IDs
- Scale from 100 to 100,000 contacts without changing your integration code
// Your SaaS backend — CRM handled by nodestash
import { NodeStash } from '@nodestash/sdk'
const crm = new NodeStash({ apiKey: process.env.NODESTASH_KEY })
// When a user signs up in your app
async function onUserSignup(user: User) {
const contact = await crm.contacts.create({
email: user.email,
first_name: user.name,
tags: ['signup', user.plan],
custom_fields: {
app_user_id: user.id,
signup_source: user.referrer,
},
})
// Auto-create a deal for onboarding
await crm.deals.create({
title: `Onboarding: ${user.company}`,
contact_id: contact.id,
pipeline_id: 'pp_onboarding',
value: user.plan === 'pro' ? 4900 : 14900,
})
}Custom CRM Frontend
Build a CRM interface that matches your brand and workflow. Use the nodestash API as your backend and React, Vue, or any framework as your frontend.
- Build exactly the UI your team needs — not what a vendor decided for you
- Embed CRM views directly in your existing application
- Full control over search, filtering, and data display
- No per-seat licensing — your whole team uses your UI
// React component using nodestash API
function ContactList() {
const { data, isLoading } = useQuery({
queryKey: ['contacts'],
queryFn: () =>
fetch('/api/crm/contacts?limit=25', {
headers: { Authorization: `Bearer ${apiKey}` },
}).then(res => res.json()),
})
return (
<div className="space-y-2">
{data?.data.map(contact => (
<ContactCard
key={contact.id}
name={`${contact.attributes.first_name} ${contact.attributes.last_name}`}
email={contact.attributes.email}
tags={contact.attributes.tags}
/>
))}
</div>
)
}Automation Workflows
Use webhooks and the API to build event-driven workflows. When a deal is won, trigger billing. When a contact is created, enrich the data. Code-driven, not click-driven.
- Webhook events for every CRM state change — contact created, deal moved, field updated
- Integrate with Stripe, Resend, Slack, or any service via code
- Build with n8n, Zapier, or your own webhook handlers
- No workflow builder limitations — if you can code it, you can automate it
// n8n / Zapier / custom webhook handler
app.post('/webhooks/nodestash', async (req, res) => {
const event = req.body
switch (event.event) {
case 'deal.stage_changed':
if (event.data.attributes.stage === 'won') {
// Trigger Stripe subscription
await stripe.subscriptions.create({
customer: event.data.attributes.stripe_id,
items: [{ price: 'price_pro_monthly' }],
})
// Send welcome email via Resend
await resend.emails.send({
to: event.data.attributes.contact_email,
subject: 'Welcome aboard!',
template: 'deal-won',
})
}
break
case 'contact.created':
// Enrich with Clearbit
const enriched = await clearbit.enrich(event.data.attributes.email)
await crm.contacts.update(event.data.id, {
company_id: enriched.company_id,
custom_fields: { industry: enriched.industry },
})
break
}
})AI Agent Integration
Give your AI agents structured access to customer data. Use the TypeScript SDK or our MCP server to let AI models look up contacts, check deal status, and log interactions.
- MCP server for direct integration with Claude, Cursor, and MCP-compatible clients
- Structured data access — search, filter, and query CRM records programmatically
- Activity logging to track every AI interaction for audit and training
- Custom fields to store AI-generated metadata like lead scores and summaries
// AI agent with CRM tool access via MCP
import { NodeStash } from '@nodestash/sdk'
const crm = new NodeStash({ apiKey: process.env.NODESTASH_KEY })
// Tool: Look up customer context
async function getCustomerContext(email: string) {
const contacts = await crm.contacts.list({
search: email,
})
if (!contacts.data.length) return null
const contact = contacts.data[0]
const deals = await crm.deals.list({
contact_id: contact.id,
})
const activities = await crm.activities.list({
contact_id: contact.id,
limit: 10,
})
return {
contact: contact.attributes,
deals: deals.data.map(d => d.attributes),
recentActivity: activities.data.map(a => a.attributes),
}
}
// The AI agent uses this context to give personalized responsesReady to build your CRM?
Get started with nodestash in minutes. No credit card required.