Insightly integrates with Bolt.new through a Next.js API route using HTTP Basic authentication with your API key. Get the key from User Settings → API, store it in .env, and call Insightly's REST API v2.3 to manage contacts, organizations, opportunities, projects, and tasks. Insightly's unique combination of CRM and project management makes it ideal for businesses that track projects after closing deals.
Insightly CRM + Project Management Integration for Bolt.new Apps
Insightly's defining feature is the combination of CRM and project management in a single platform. While most CRMs end their workflow at the deal close, Insightly continues tracking the customer relationship through project delivery — you can convert a won opportunity directly into a project, link project tasks to the original contact and organization, and maintain a complete history from first contact through project completion. For service businesses, agencies, and consulting firms that sell and then deliver, this unified model is more practical than maintaining separate CRM and project management tools.
The Insightly API v2.3 reflects this combined model. Contacts, organizations, opportunities, and projects are all first-class objects with their own endpoints, and they are linked through relationship endpoints that associate records across object types. A contact can be linked to multiple opportunities and projects; a project can have tasks assigned to specific team members; an opportunity can be converted into a project using a single API call. This relational structure makes Insightly integrations somewhat more complex than simple pipeline CRMs, but also more powerful for building custom internal tools.
For Bolt.new developers, Insightly's HTTP Basic auth with API key is one of the simplest authentication patterns available — no OAuth, no token expiration, just Base64-encode your API key with a trailing colon and you have a working Authorization header. The free plan supports 2 users with full API access, making it practical to build and test a complete integration without any cost. Common use cases include custom CRM dashboards for teams that do not need full Insightly licenses, lead capture forms on Bolt-built websites that feed into the CRM, and project status portals for clients that surface Insightly project data in a branded interface.
Integration method
Insightly uses HTTP Basic authentication with your API key as the username and an empty password. The API key is Base64-encoded with a trailing colon (key:) and sent in the Authorization header. All API requests go through Next.js server-side routes to keep the key out of the browser bundle. Insightly's REST API v2.3 supports contacts, organizations, opportunities, projects, and tasks through standard HTTP conventions.
Prerequisites
- An Insightly account (insightly.com) — the free plan supports 2 users with full API access; paid plans start at $29/user/month
- Your Insightly API key from User Settings → API key — a 36-character UUID-format string
- A Bolt.new project using Next.js for API routes that keep the API key server-side
- Your Insightly instance API URL (typically https://api.insightly.com/v3.1 but may differ for enterprise plans) — verify in your Insightly Settings under API
- Optional: Insightly pipeline stage IDs for creating opportunities in specific stages — retrieve via GET /v3.1/Opportunities/Pipelines
Step-by-step guide
Get your Insightly API key and configure Basic auth
Get your Insightly API key and configure Basic auth
Insightly uses HTTP Basic authentication with your API key as the username and an empty password. The Basic auth header is constructed by Base64-encoding the string 'YOUR_API_KEY:' (note the trailing colon with nothing after it, representing an empty password). This unusual format is specific to Insightly and differs from standard Basic auth where both username and password are typically non-empty. To get your API key, log into Insightly and click your user avatar in the top-right corner, then select 'User Settings.' Scroll to the API section. You will see your personal API key — a 36-character UUID-format string (groups of hexadecimal characters separated by hyphens, like 12345678-abcd-1234-abcd-123456789abc). Copy it. The API key provides the same level of access as your Insightly user account. If you are an administrator, the key gives admin-level access. For production integrations, consider creating a dedicated API user with limited permissions if your plan supports multiple users. Insightly's API base URL is https://api.insightly.com/v3.1 for most accounts. Enterprise plans on dedicated infrastructure use different base URLs — check your Insightly Settings under the API section for your specific instance URL. Store this as INSIGHTLY_BASE_URL in .env so you can easily change it if needed. Construct the Basic auth header in Node.js as follows: take the API key string, add a colon at the end (key + ':'), Base64-encode the entire string, and prefix it with 'Basic '. This is different from standard Basic auth — the 'password' field is intentionally empty. Store the raw API key in .env as INSIGHTLY_API_KEY and construct the header in your service module at runtime. Outbound API calls to api.insightly.com work in Bolt's WebContainer preview since they use standard HTTPS. You can test the full integration — fetching contacts, creating opportunities — directly in the Bolt preview without deploying first.
Add Insightly API credentials to .env. Create the file with: INSIGHTLY_API_KEY=your-api-key-uuid-here (server-side only, never NEXT_PUBLIC_) and INSIGHTLY_BASE_URL=https://api.insightly.com/v3.1. Add a comment explaining that Insightly uses Basic auth with the API key as username and empty password (base64 of 'api_key:').
Paste this in Bolt.new chat
1# .env2# Insightly API key — server-side only, never NEXT_PUBLIC_3# Get from Insightly: User avatar → User Settings → API section4# Format: UUID-style string (12345678-abcd-1234-abcd-123456789abc)5INSIGHTLY_API_KEY=your-api-key-here67# Insightly API base URL — usually https://api.insightly.com/v3.18# Enterprise customers may have a custom base URL — verify in Settings → API9INSIGHTLY_BASE_URL=https://api.insightly.com/v3.1Pro tip: Insightly's Basic auth uses an empty password — encode 'YOUR_API_KEY:' (with trailing colon) as Base64. In Node.js: Buffer.from(`${apiKey}:`).toString('base64'). Omitting the colon causes authentication failures even though the key itself is correct.
Expected result: The Insightly API key is stored in .env. You can test it by making a GET request to https://api.insightly.com/v3.1/Contacts with the Basic auth header — it should return your Insightly contacts as JSON without any additional configuration.
Build the Insightly API service and contact management routes
Build the Insightly API service and contact management routes
Create the Insightly API service module with typed helper functions for the most common operations, and build Next.js API routes for contacts, organizations, opportunities, and projects. Insightly's REST API v3.1 is RESTful but uses uppercase field names (FIRST_NAME, LAST_NAME, EMAIL_ADDRESS, OPPORTUNITY_NAME) rather than the camelCase or snake_case common in newer APIs. This is a holdover from the platform's older architecture — always check the Insightly API documentation for exact field names, as the capitalization matters. The key object types and their primary fields are: Contacts (CONTACT_ID, FIRST_NAME, LAST_NAME, EMAIL_ADDRESS, PHONE, ORGANISATION_ID), Organisations (ORGANISATION_ID, ORGANISATION_NAME, PHONE, WEBSITE), Opportunities (OPPORTUNITY_ID, OPPORTUNITY_NAME, OPPORTUNITY_STATE, BID_AMOUNT, CLOSE_DATE, PIPELINE_ID, STAGE_ID, ORGANISATION_ID, RESPONSIBLE_USER_ID), and Projects (PROJECT_ID, PROJECT_NAME, STATUS, STARTED_DATE, COMPLETED_DATE, RESPONSIBLE_USER_ID). Insightly's pagination uses skip and top parameters rather than page numbers: GET /Contacts?skip=0&top=50 returns the first 50 contacts. For large datasets, increment skip by top to retrieve subsequent pages. Links between objects use a LINKS array in the response and request bodies: [{ 'LINK_OBJECT_NAME': 'Contact', 'LINK_OBJECT_ID': 12345, 'ROLE': 'Responsible' }]. This linking mechanism connects contacts to opportunities, opportunities to projects, and tasks to any object type. Understanding links is essential for building the combined CRM + project dashboard that surfaces Insightly's unique value.
Create an Insightly API integration for this Next.js app. (1) Create lib/insightly.ts with an insightlyFetch(endpoint, options) utility using INSIGHTLY_API_KEY Basic auth (base64 of 'key:') and INSIGHTLY_BASE_URL. Export: getContacts(skip, top), createContact(fields), getOrganizations(skip, top), createOrganization(name), getOpportunities(state), createOpportunity(fields), getProjects(status), and createLink(objectName, objectId, linkedObjectName, linkedObjectId). Use UPPERCASE field names for Insightly objects. (2) Create app/api/insightly/contacts/route.ts with GET and POST handlers. (3) Create app/api/insightly/opportunities/route.ts with GET (filter by state: OPEN, WON, LOST, ABANDONED) and POST. Include TypeScript interfaces for Insightly objects.
Paste this in Bolt.new chat
1// lib/insightly.ts2function getInsightlyAuth(): string {3 const key = process.env.INSIGHTLY_API_KEY;4 if (!key) throw new Error('INSIGHTLY_API_KEY not configured');5 // Insightly Basic auth: Base64 of 'api_key:' (empty password)6 return Buffer.from(`${key}:`).toString('base64');7}89const BASE = () => {10 const url = process.env.INSIGHTLY_BASE_URL ?? 'https://api.insightly.com/v3.1';11 return url;12};1314async function insightlyFetch<T>(path: string, options: RequestInit = {}): Promise<T> {15 const res = await fetch(`${BASE()}${path}`, {16 ...options,17 headers: {18 Authorization: `Basic ${getInsightlyAuth()}`,19 'Content-Type': 'application/json',20 Accept: 'application/json',21 ...options.headers,22 },23 });2425 if (!res.ok) {26 const body = await res.text();27 throw Object.assign(new Error(`Insightly API error: ${res.status}`), {28 status: res.status,29 body,30 });31 }3233 return res.json();34}3536export interface InsightlyContact {37 CONTACT_ID?: number;38 FIRST_NAME: string;39 LAST_NAME: string;40 EMAIL_ADDRESS?: string;41 PHONE?: string;42 ORGANISATION_ID?: number;43}4445export interface InsightlyOpportunity {46 OPPORTUNITY_ID?: number;47 OPPORTUNITY_NAME: string;48 OPPORTUNITY_STATE?: string;49 BID_AMOUNT?: number;50 CLOSE_DATE?: string;51 ORGANISATION_ID?: number;52 PIPELINE_ID?: number;53 STAGE_ID?: number;54}5556export async function getContacts(skip = 0, top = 50) {57 return insightlyFetch<InsightlyContact[]>(`/Contacts?skip=${skip}&top=${top}`);58}5960export async function createContact(fields: InsightlyContact) {61 return insightlyFetch<InsightlyContact>('/Contacts', {62 method: 'POST',63 body: JSON.stringify(fields),64 });65}6667export async function createOrganization(name: string) {68 return insightlyFetch<{ ORGANISATION_ID: number }>('/Organisations', {69 method: 'POST',70 body: JSON.stringify({ ORGANISATION_NAME: name }),71 });72}7374export async function getOpportunities(state?: string) {75 const filter = state ? `?opportunity_state=${state}` : '';76 return insightlyFetch<InsightlyOpportunity[]>(`/Opportunities${filter}`);77}7879export async function createOpportunity(fields: InsightlyOpportunity) {80 return insightlyFetch<InsightlyOpportunity>('/Opportunities', {81 method: 'POST',82 body: JSON.stringify(fields),83 });84}8586export async function getProjects(status?: string) {87 const filter = status ? `?status=${status}` : '';88 return insightlyFetch<Array<{ PROJECT_ID: number; PROJECT_NAME: string; STATUS: string }>>(89 `/Projects${filter}`90 );91}Pro tip: Insightly API field names are UPPERCASE_WITH_UNDERSCORES for all built-in fields. Custom fields you add in Insightly use the format CUSTOMFIELDS: [{ FIELD_NAME: 'my_field', FIELD_VALUE: 'value' }]. Check the Insightly API explorer (appui.insightly.com/APIExplorer) for exact field names and required fields for each object type.
Expected result: lib/insightly.ts provides authenticated access to Insightly's REST API using Basic auth. The contacts and opportunities API routes list and create records. Outbound calls to api.insightly.com work in the Bolt WebContainer preview — real Insightly data appears in the dashboard during development.
Build the combined CRM and project management dashboard
Build the combined CRM and project management dashboard
Insightly's unique value proposition is linking opportunities (sales) to projects (delivery). Build a dashboard that surfaces both, giving account managers and project managers a single view of the full customer lifecycle from initial lead through project completion. The dashboard has two main sections: an opportunities pipeline view showing active deals organized by stage (similar to a Kanban CRM), and a projects panel showing active project delivery with completion status. The key feature that makes this more than two separate views is linking them: when an opportunity is won and converted to a project, the dashboard should connect them visually — showing the transition from 'Closed Won' to 'In Progress Project.' Fetch opportunities with OPPORTUNITY_STATE=OPEN for the pipeline view. For projects, fetch with STATUS=IN_PROGRESS. To connect the two, use Insightly's CONVERTED_TO_PROJECT field on opportunities (a boolean indicating conversion) and the LINKS array that contains references to related objects. For the opportunity pipeline, group by PIPELINE_ID and then by STAGE_ID within each pipeline. Display stages in order using the stage order from GET /v3.1/Opportunities/Pipelines. Each opportunity card shows the amount (BID_AMOUNT), expected close date (CLOSE_DATE), and the linked organization name (ORGANISATION_NAME). For the projects panel, show a progress indicator based on completed vs total tasks. Fetch project tasks via GET /v3.1/Projects/{PROJECT_ID}/Tasks and count completed vs incomplete to calculate a percentage. Display a simple progress bar and a list of upcoming due tasks.
Build an Insightly CRM + Project dashboard at app/dashboard/insightly/page.tsx. Make two parallel API calls: GET /api/insightly/opportunities?state=OPEN and GET /api/insightly/projects?status=IN_PROGRESS. Display a two-panel layout: left panel 'Sales Pipeline' with opportunity cards showing name, amount, close date, and company; right panel 'Active Projects' with project cards showing name, status badge (IN_PROGRESS, COMPLETED, DEFERRED), started date, and team member count. Add a count summary row at the top: total open opportunity value, number of active projects. Use Tailwind CSS with a sidebar layout. Mark opportunities that have CONVERTED_TO_PROJECT=true with a 'Converted' badge and show them in both panels.
Paste this in Bolt.new chat
1// app/api/insightly/dashboard/route.ts2import { NextResponse } from 'next/server';3import { getOpportunities, getProjects } from '@/lib/insightly';45export async function GET() {6 try {7 const [opportunities, projects] = await Promise.all([8 getOpportunities('OPEN'),9 getProjects('IN_PROGRESS'),10 ]);1112 const totalOpportunityValue = (opportunities ?? []).reduce(13 (sum, opp) => sum + (opp.BID_AMOUNT ?? 0),14 015 );1617 return NextResponse.json({18 opportunities: opportunities ?? [],19 projects: projects ?? [],20 summary: {21 totalOpportunityValue,22 openOpportunities: opportunities?.length ?? 0,23 activeProjects: projects?.length ?? 0,24 },25 });26 } catch (error) {27 const message = error instanceof Error ? error.message : 'Unknown error';28 return NextResponse.json({ error: message }, { status: 500 });29 }30}Pro tip: Insightly's opportunity states are: OPEN (active in pipeline), WON, LOST, ABANDONED, SUSPENDED. For a complete pipeline view including recently won deals, fetch both OPEN and WON states and display them in separate sections.
Expected result: The dashboard shows active opportunities and in-progress projects side by side. The summary row displays total pipeline value and project count. Opportunities with CONVERTED_TO_PROJECT=true have a 'Converted' badge, visually linking them to the active projects panel.
Add note and activity tracking to Insightly records
Add note and activity tracking to Insightly records
Insightly's activity and notes system is key to using it as a full CRM — recording calls, meetings, and emails on contacts and opportunities provides context for the sales team and creates an audit trail of customer interactions. Insightly has two types of activity records: Notes (text-based comments attached to contacts, opportunities, or projects) and Tasks (actionable items with due dates and assigned users). Both use the same LINKS array mechanism to attach them to parent records. Create notes via POST /v3.1/Notes with a TITLE, NOTE_TEXT, and a LINKS array connecting the note to its parent object. For example, to add a note to an opportunity: { 'TITLE': 'Call with client', 'NOTE_TEXT': 'Discussed requirements...', 'LINKS': [{ 'LINK_OBJECT_NAME': 'Opportunity', 'LINK_OBJECT_ID': 12345 }] }. Create tasks via POST /v3.1/Tasks with TITLE, DUE_DATE, COMPLETED (boolean), RESPONSIBLE_USER_ID, and a LINKS array. Tasks appear in the Insightly UI as action items and can trigger notification emails to the assigned user when created via API. For the Bolt.new integration, add a form that allows team members to log notes against Insightly opportunities from the dashboard — a textarea that submits to a /api/insightly/notes route. This avoids the need to open Insightly just to log a quick call note, keeping team members in your custom interface while still maintaining Insightly as the system of record.
Add note logging to the Insightly dashboard. (1) Create app/api/insightly/notes/route.ts with POST that accepts { title, text, opportunityId } and creates a note in Insightly at /v3.1/Notes with TITLE, NOTE_TEXT, and LINKS array linking to the opportunity. Use INSIGHTLY_API_KEY Basic auth. (2) Create app/api/insightly/tasks/route.ts with POST accepting { title, dueDate, opportunityId, assignedUserId } creating a task in Insightly. (3) Add a quick note form to each opportunity card in the dashboard: a textarea and 'Log Note' button that POSTs to /api/insightly/notes. Show a success toast when the note is created. Optimistically add the note to the card's note count.
Paste this in Bolt.new chat
1// app/api/insightly/notes/route.ts2import { NextResponse } from 'next/server';34export async function POST(request: Request) {5 const { title, text, opportunityId, contactId } = await request.json();67 const apiKey = process.env.INSIGHTLY_API_KEY;8 const base = process.env.INSIGHTLY_BASE_URL ?? 'https://api.insightly.com/v3.1';910 if (!apiKey) {11 return NextResponse.json({ error: 'INSIGHTLY_API_KEY not configured' }, { status: 500 });12 }1314 const links: Array<{ LINK_OBJECT_NAME: string; LINK_OBJECT_ID: number }> = [];15 if (opportunityId) links.push({ LINK_OBJECT_NAME: 'Opportunity', LINK_OBJECT_ID: opportunityId });16 if (contactId) links.push({ LINK_OBJECT_NAME: 'Contact', LINK_OBJECT_ID: contactId });1718 const res = await fetch(`${base}/Notes`, {19 method: 'POST',20 headers: {21 Authorization: `Basic ${Buffer.from(`${apiKey}:`).toString('base64')}`,22 'Content-Type': 'application/json',23 },24 body: JSON.stringify({25 TITLE: title,26 NOTE_TEXT: text,27 LINKS: links,28 }),29 });3031 if (!res.ok) {32 return NextResponse.json({ error: 'Failed to create note' }, { status: res.status });33 }3435 const note = await res.json();36 return NextResponse.json({ noteId: note.NOTE_ID, title: note.TITLE });37}Pro tip: Insightly note text supports plain text with newlines. Do not include HTML tags in NOTE_TEXT — Insightly does not render HTML in notes and the tags will appear as literal text in the Insightly UI.
Expected result: Team members can log notes on opportunities directly from the Bolt dashboard without opening Insightly. Notes appear immediately in the Insightly UI under the linked opportunity. The note count on each opportunity card updates optimistically after submission.
Common use cases
Combined CRM and Project Status Dashboard
An internal dashboard showing active Insightly opportunities alongside their linked projects and tasks. Account managers see both the sales pipeline and delivery status in one view — opportunities in progress, recently won deals that have been converted to projects, and project completion percentages for currently active work.
Build an Insightly combined CRM dashboard. Create /api/insightly/opportunities that GETs https://api.insightly.com/v3.1/Opportunities?brief=false using INSIGHTLY_API_KEY Basic auth. Return id, OPPORTUNITY_NAME, OPPORTUNITY_STATE, BID_AMOUNT, CLOSE_DATE, and ORGANISATION_NAME. Create /api/insightly/projects that GETs /Projects?brief=false and returns id, PROJECT_NAME, STATUS, COMPLETED_DATE, and linked contacts. In React, display two sections: 'Active Opportunities' (in progress deals) and 'Active Projects' (in progress deliveries). Link opportunities to their converted projects where CONVERTED_TO_PROJECT is true. Use Tailwind CSS with a clean two-column layout.
Copy this prompt to try it in Bolt.new
Lead Capture Form Creating Insightly Contacts and Opportunities
A website contact form that creates an Insightly contact and a linked opportunity when submitted. The opportunity is placed in the first stage of the sales pipeline and assigned to the appropriate team member based on form data. Notes from the form message are attached to the opportunity for context.
Create a lead capture form that creates contacts and opportunities in Insightly. Build a form with firstName, lastName, email, phone, company, and message fields. On submit, POST to /api/insightly/leads which: (1) Creates a contact via POST to https://api.insightly.com/v3.1/Contacts with FIRST_NAME, LAST_NAME, EMAIL_ADDRESS, PHONE fields using INSIGHTLY_API_KEY Basic auth, (2) Creates an organization with ORGANISATION_NAME = company, (3) Creates an opportunity with OPPORTUNITY_NAME = '{firstName} {lastName} - Inbound', ORGANISATION_ID, and a note containing the message. Return the opportunity ID. Show a thank-you message on success.
Copy this prompt to try it in Bolt.new
Project Tracking Portal for Clients
A client-facing project status portal built in Bolt.new that surfaces Insightly project data — milestones, task completion percentages, team members, and deadlines — in a branded interface. Clients can check project status without needing Insightly accounts or logins to the internal CRM system.
Create a project status portal. Create /api/insightly/projects/[id] that GETs https://api.insightly.com/v3.1/Projects/{id} with task details and returns project name, status, percentage complete, start date, end date, and a list of tasks with their completion status. Create /api/insightly/projects that returns all active projects. In React, build a portal with a project list sidebar and a detail panel showing: project name, completion progress bar, upcoming tasks (due within 7 days), overdue tasks (highlighted red), and team member names. Use Tailwind CSS with a clean client-friendly design.
Copy this prompt to try it in Bolt.new
Troubleshooting
Insightly API returns 401 Unauthorized with the API key
Cause: The Basic auth header is incorrectly formatted. Insightly requires Base64 encoding of 'API_KEY:' (with a trailing colon and empty password). Omitting the colon, or encoding just the API key without the colon, causes authentication failure.
Solution: Verify the auth construction: Buffer.from(`${apiKey}:`).toString('base64') — note the colon appended to the API key. The full Authorization header should be 'Basic ' followed by the Base64 string. Also verify the API key has no leading or trailing whitespace in .env.
1// Correct Insightly Basic auth construction2const apiKey = process.env.INSIGHTLY_API_KEY;3// CORRECT: append ':' before encoding (empty password)4const auth = Buffer.from(`${apiKey}:`).toString('base64');5// WRONG: encoding just the key6// const auth = Buffer.from(apiKey).toString('base64');7const headers = { Authorization: `Basic ${auth}` };POST to /Contacts or /Opportunities returns 400 Bad Request
Cause: Insightly's API uses UPPERCASE field names (FIRST_NAME, not firstName). Sending camelCase or snake_case field names in the request body causes validation errors since Insightly does not recognize the field names.
Solution: Check your request body uses Insightly's UPPERCASE field naming convention. Key fields: FIRST_NAME, LAST_NAME, EMAIL_ADDRESS (not 'email'), OPPORTUNITY_NAME (not 'name'), BID_AMOUNT (not 'amount'), CLOSE_DATE (ISO format: YYYY-MM-DDT00:00:00). Verify against the Insightly API documentation or the API Explorer at your Insightly instance URL + /api_explorer.
1// Correct Insightly contact field names (UPPERCASE)2const contact = {3 FIRST_NAME: formData.firstName, // NOT: firstName4 LAST_NAME: formData.lastName, // NOT: lastName5 EMAIL_ADDRESS: formData.email, // NOT: email or emailAddress6 PHONE: formData.phone,7 ORGANISATION_ID: orgId, // NOT: organizationId8};Insightly API returns empty arrays even though data exists in the Insightly UI
Cause: Insightly's list endpoints return empty arrays (not 404) when the API user does not have access to the requested records, or when the filter parameters exclude all existing records. This is common with opportunity state filters.
Solution: Try fetching without state filters first to verify the API key works: GET /Opportunities (without ?opportunity_state=). If records appear, your filter is excluding them. Check the OPPORTUNITY_STATE values — Insightly uses OPEN, WON, LOST, ABANDONED, SUSPENDED (all uppercase). Lowercase state values cause the filter to return empty results rather than an error.
Best practices
- Store the INSIGHTLY_API_KEY in server-side .env with no NEXT_PUBLIC_ prefix — it gives read/write access to all CRM data and project information in your Insightly account
- Use Insightly's LINKS array to connect related records rather than storing foreign IDs in custom fields — linked records appear in the Insightly UI with the correct relationship labels and enable navigation between related objects
- Cache organization and pipeline stage lists in React state or API-level caching — these change infrequently and fetching them on every page load adds unnecessary API calls
- Always use UPPERCASE field names in API payloads — Insightly's API rejects camelCase and snake_case field names without a descriptive error message, making typos hard to debug
- For the combined CRM + project view, fetch opportunities and projects in parallel using Promise.all rather than sequentially — both requests are independent and parallelizing them halves load time
- Use Insightly's skip/top pagination for large datasets rather than increasing the limit indefinitely — fetching all records in one request can cause timeouts for accounts with thousands of contacts
- Test the full contact → opportunity → project creation workflow in Bolt's WebContainer preview before deploying — outbound HTTPS calls to Insightly work in the preview, so you can validate the complete data flow without a deployment
Alternatives
Choose Pipedrive over Insightly if your primary need is sales pipeline management and you do not need post-sale project tracking — Pipedrive's deal-focused UI and API are simpler for pure sales workflows.
Choose HubSpot over Insightly if you need marketing automation alongside CRM — HubSpot has a more powerful free tier and stronger email marketing integration than Insightly's CRM features.
Choose Asana over Insightly's project management features if project delivery is your primary use case — Asana offers more sophisticated project planning, timeline views, and team collaboration tools.
Choose Teamwork over Insightly if you run a client services business and need project management with client portals, time tracking, and billing — Teamwork is purpose-built for agencies.
Frequently asked questions
Does Insightly work with Bolt.new?
Yes. Insightly's REST API v2.3/3.1 uses standard HTTPS requests that work in Bolt's WebContainer via a Next.js API route. Insightly uses HTTP Basic auth with an API key, so there is no OAuth flow or redirect URI requirement. You can test the complete integration — fetching and creating contacts, opportunities, and projects — directly in the Bolt preview without deploying.
How do I connect Bolt.new to Insightly?
Get your API key from Insightly User Settings → API section. Store it in .env as INSIGHTLY_API_KEY. Create a Next.js API route that constructs Basic auth by encoding 'API_KEY:' (with trailing colon) as Base64 and adds it as an Authorization header to requests to https://api.insightly.com/v3.1. All API calls go through server-side routes — never directly from the browser.
What makes Insightly different from other CRMs for Bolt.new integrations?
Insightly uniquely combines CRM (contacts, opportunities, pipeline) with project management (projects, milestones, tasks) in a single platform. This makes it ideal for service businesses that sell and then deliver — you can convert a won opportunity to a project and track the full customer lifecycle in one tool. The API supports this with LINKS arrays connecting records across object types.
Is there a free tier for Insightly API access?
Yes. Insightly's free plan supports 2 users with full API access to contacts, organizations, opportunities, and projects. The free plan has limits on records (2,500 contacts, 2,500 organizations, 2,500 opportunities) and lacks some advanced features, but provides enough access to build and test a complete Bolt.new integration. Paid plans start at $29/user/month.
Why do I need to use UPPERCASE field names in Insightly API requests?
Insightly's REST API v3.1 uses UPPERCASE_WITH_UNDERSCORES naming for all built-in fields (FIRST_NAME, EMAIL_ADDRESS, OPPORTUNITY_NAME). This is a design choice from the platform's architecture and is consistently applied across all object types. Sending camelCase or snake_case field names causes 400 errors without a descriptive message, so always double-check field names against Insightly's API documentation.
Can I link Insightly opportunities to projects from Bolt.new?
Yes. Use Insightly's LINKS array in API request bodies to associate records across object types. To link a project to an opportunity, include a LINKS array containing { LINK_OBJECT_NAME: 'Opportunity', LINK_OBJECT_ID: opportunityId } in the project creation payload. Linked records appear in the Insightly UI with navigable relationship indicators and are returned in the LINKS array of GET responses.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation