To integrate Insightly with Lovable, find your API key in Insightly User Settings, store it with the API endpoint URL in Cloud → Secrets, then build Edge Functions that call the Insightly REST API v3.1 for contacts, organizations, opportunities, and projects. Insightly's unique CRM-to-project pipeline — where won deals automatically create delivery projects — makes it ideal for service businesses building client management tools in Lovable.
Build CRM-to-project delivery tools in Lovable with Insightly's linked-record API
Insightly occupies a distinctive niche in the CRM market: it bridges sales pipeline management and project delivery in a single platform. When a sales opportunity is marked as 'Won' in Insightly, it can automatically create a linked project for service delivery. For consulting firms, agencies, software development shops, and any service business where the sales win initiates a delivery workflow, this CRM-to-project linkage is uniquely valuable. Building Lovable apps on top of Insightly lets these businesses create custom client portals and project tracking dashboards without duplicating data between separate CRM and project management tools.
Insightly's API v3.1 is REST-based with JSON responses. Authentication uses HTTP Basic Auth with the API key as the username and an empty string as the password — a common pattern for API key-based Basic Auth. The API key is base64-encoded in the Authorization header: btoa(apiKey + ':').
The Insightly data model includes Contacts (individual people), Organizations (companies), Opportunities (deals in the sales pipeline), Projects (delivery work linked to won opportunities), Tasks, Events, and Leads. Opportunities and Projects can be linked via the 'OPPORTUNITY_STATE' relationship, and the transition from Opportunity to Project is tracked through the pipeline stages.
For Lovable apps, the most valuable use cases are client portals (clients see their project status linked to their opportunity history), internal CRM dashboards showing both sales pipeline and active projects for account managers, and automated project creation triggers when opportunities are moved to 'Won' status.
Integration method
Insightly has no native Lovable connector. All CRM and project operations are proxied through Lovable Edge Functions that call the Insightly REST API v3.1. The API key is stored in Cloud → Secrets and used in HTTP Basic Auth (as the username with an empty password), keeping credentials server-side and preventing CORS issues from direct browser calls.
Prerequisites
- A Lovable project with Lovable Cloud enabled (Edge Functions require a deployed app)
- An Insightly account (free plan available for 2 users at insightly.com — API access included)
- Your Insightly User Settings page access to find your API key
- Basic familiarity with Insightly's data model: Contacts, Organizations, Opportunities, Projects, and how they link
Step-by-step guide
Find your Insightly API key and API endpoint URL
Find your Insightly API key and API endpoint URL
Insightly uses API key authentication. Your personal API key is found in your Insightly account User Settings. To get your API key: log in to Insightly and click your profile avatar in the top-right corner. Select 'User Settings' from the dropdown. In User Settings, scroll to the 'API Key' section. Your API key is displayed — click the eye icon to show it and copy the full key string. The Insightly API base URL depends on which Insightly environment your account is on. Most Insightly accounts use: https://api.na1.insightly.com/v3.1/ (North America). However, Insightly has multiple regional endpoints: - North America: https://api.na1.insightly.com/v3.1/ - Europe/Australia: check your Insightly URL — if it ends in .co.uk or .com.au, use the eu1 endpoint To verify your endpoint: your Insightly account URL in the browser shows the region. For most US-based accounts, the API URL is https://api.na1.insightly.com/v3.1/. Insightly API authentication: HTTP Basic Auth with the API key as the username and an empty string as the password. In Base64: btoa(apiKey + ':'). The colon separates username from password in Basic Auth — with an empty password, the colon must still be present. Insightly also provides a unique API URL per user visible at the bottom of the User Settings page under 'API URL' — this shows your exact regional API base URL. Use this value directly.
Pro tip: Your Insightly API URL is shown directly on the User Settings page — look for 'API URL' near the API key. Copy this URL exactly as the API base URL rather than guessing the regional endpoint. It includes the correct na1, eu1, or other regional identifier.
Expected result: An Insightly API key is copied from User Settings. The correct regional API base URL is noted from the same settings page. Both are ready to store in Cloud → Secrets.
Store credentials in Cloud Secrets
Store credentials in Cloud Secrets
Add Insightly credentials to Lovable's Cloud Secrets panel. In Lovable, click '+' → Cloud panel → Secrets. Add two secrets: - INSIGHTLY_API_KEY — your personal API key from Insightly User Settings - INSIGHTLY_API_URL — the full API base URL from Insightly User Settings (e.g., https://api.na1.insightly.com/v3.1/) The Edge Function constructs API endpoints by appending resource paths to the base URL: contacts, organizations, opportunities, projects. The Authorization header is constructed as: btoa(INSIGHTLY_API_KEY + ':'). Note the colon after the key — this is the HTTP Basic Auth separator between username (API key) and password (empty string). Insightly API v3.1 supports standard REST methods. List endpoints accept skip and top query parameters for pagination (Insightly uses top for page size and skip for offset). The default page size is 100 records — use $top and $skip for pagination: GET /contacts?$top=25&$skip=50 — returns records 51-75. Insightly also uses OData-style filter syntax for searching: GET /contacts?brief=false&top=10&skip=0&convertDates=true returns structured date objects. For searching by email: GET /contacts/search?field_name=EMAIL_ADDRESS&field_value=user@example.com.
Pro tip: Include the trailing slash in INSIGHTLY_API_URL when storing it. The Edge Function appends resource names directly to the base URL, so https://api.na1.insightly.com/v3.1/contacts (with trailing slash in base) is correct. Without the trailing slash, you get double-slash URLs.
Expected result: INSIGHTLY_API_KEY and INSIGHTLY_API_URL appear in Cloud → Secrets with masked values.
Create the Insightly REST API proxy Edge Function
Create the Insightly REST API proxy Edge Function
Build the Edge Function that handles Insightly operations. The function constructs the Basic Auth header and proxies requests to the correct Insightly API endpoint. Insightly API v3.1 endpoint patterns: - Contacts: GET /contacts, POST /contacts, GET /contacts/{id}, PUT /contacts/{id} - Organizations: GET /organisations, POST /organisations (note UK spelling) - Opportunities: GET /opportunities, POST /opportunities, PUT /opportunities/{id} - Projects: GET /projects, POST /projects, PUT /projects/{id} - Search contacts by email: GET /contacts/search?field_name=EMAIL_ADDRESS&field_value=user@example.com Insightly uses UK English in some endpoint names: 'organisations' (not 'organizations'). This is a common source of 404 errors. For creating linked records (opportunity linked to a contact and organization), Insightly uses a 'LINKS' array in the request body. Each link specifies the linked record type and ID: { LINK_SUBJECT_TYPE: 'CONTACT', LINK_SUBJECT_ID: contactId, ROLE: 'Responsible' }. Opportunity OPPORTUNITY_STATE field values: 'OPEN', 'WON', 'ABANDONED', 'LOST', 'SUSPENDED'. Project STATUS field values: 'NOT_STARTED', 'IN_PROGRESS', 'COMPLETED', 'OVERDUE', 'ABANDONED'. Insightly returns dates in ISO 8601 format and uses nullable fields liberally — handle null values in your React components to avoid undefined rendering errors.
Create an Edge Function called insightly-crm at supabase/functions/insightly-crm/index.ts. Accept POST with { action, params }. Support actions: list_contacts, search_contact, create_contact, list_opportunities, create_opportunity, update_opportunity_state, list_projects, create_project. Use INSIGHTLY_API_KEY in Basic Auth (btoa(key + ':')) and INSIGHTLY_API_URL. Note: organizations endpoint uses UK spelling 'organisations'. Include CORS headers.
Paste this in Lovable chat
1import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'23const corsHeaders = {4 'Access-Control-Allow-Origin': '*',5 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',6}78function insightlyHeaders() {9 const key = Deno.env.get('INSIGHTLY_API_KEY')10 if (!key) throw new Error('INSIGHTLY_API_KEY not configured')11 return {12 Authorization: `Basic ${btoa(key + ':')}`,13 'Content-Type': 'application/json',14 Accept: 'application/json',15 }16}1718function insightlyUrl(path: string) {19 const base = Deno.env.get('INSIGHTLY_API_URL')!20 return `${base}${path}`21}2223serve(async (req) => {24 if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders })2526 try {27 const { action, params = {} } = await req.json()28 const headers = insightlyHeaders()29 let resp: Response3031 switch (action) {32 case 'list_contacts':33 resp = await fetch(insightlyUrl(`contacts?top=${params.top || 25}&skip=${params.skip || 0}`), { headers })34 break3536 case 'search_contact':37 resp = await fetch(insightlyUrl(`contacts/search?field_name=EMAIL_ADDRESS&field_value=${encodeURIComponent(params.email)}`), { headers })38 break3940 case 'create_contact':41 resp = await fetch(insightlyUrl('contacts'), {42 method: 'POST',43 headers,44 body: JSON.stringify({45 FIRST_NAME: params.firstName,46 LAST_NAME: params.lastName,47 EMAIL_ADDRESS: params.email,48 PHONE: params.phone || '',49 ORGANISATION_ID: params.organisationId,50 }),51 })52 break5354 case 'list_opportunities':55 resp = await fetch(insightlyUrl(`opportunities?top=${params.top || 25}&skip=${params.skip || 0}`), { headers })56 break5758 case 'create_opportunity':59 resp = await fetch(insightlyUrl('opportunities'), {60 method: 'POST',61 headers,62 body: JSON.stringify({63 OPPORTUNITY_NAME: params.name,64 OPPORTUNITY_STATE: 'OPEN',65 BID_AMOUNT: params.amount,66 BID_CURRENCY: params.currency || 'USD',67 CLOSE_DATE: params.closeDate,68 RESPONSIBLE_USER_ID: params.responsibleUserId,69 LINKS: params.links || [],70 }),71 })72 break7374 case 'update_opportunity_state':75 resp = await fetch(insightlyUrl(`opportunities/${params.opportunityId}`), {76 method: 'PUT',77 headers,78 body: JSON.stringify({ OPPORTUNITY_STATE: params.state }),79 })80 break8182 case 'list_projects':83 resp = await fetch(insightlyUrl(`projects?top=${params.top || 25}&skip=${params.skip || 0}`), { headers })84 break8586 case 'create_project':87 resp = await fetch(insightlyUrl('projects'), {88 method: 'POST',89 headers,90 body: JSON.stringify({91 PROJECT_NAME: params.name,92 STATUS: 'IN_PROGRESS',93 RESPONSIBLE_USER_ID: params.responsibleUserId,94 START_DATE: params.startDate || new Date().toISOString().split('T')[0],95 END_DATE: params.endDate,96 LINKS: params.links || [],97 }),98 })99 break100101 default:102 return new Response(JSON.stringify({ error: 'Unknown action' }), {103 status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' },104 })105 }106107 const data = await resp.json()108 return new Response(JSON.stringify(data), {109 status: resp.ok ? 200 : resp.status,110 headers: { ...corsHeaders, 'Content-Type': 'application/json' },111 })112 } catch (error) {113 return new Response(JSON.stringify({ error: error.message }), {114 status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' },115 })116 }117})Pro tip: Insightly uses UK English for some API endpoints — 'organisations' (not 'organizations'). This trips up many developers. Similarly, some field names use UK spellings. Always cross-reference with the Insightly API documentation for exact endpoint and field names.
Expected result: The insightly-crm Edge Function deploys in Cloud → Edge Functions. Test with action 'list_contacts' — Insightly contact records should appear in the response.
Build the CRM-to-project pipeline view in Lovable
Build the CRM-to-project pipeline view in Lovable
With the Edge Function deployed, use Lovable's chat to build the dashboard that makes Insightly's linked opportunity-to-project model visible. This is the unique value of Insightly — a single view showing both pipeline status and delivery progress. For the combined sales and projects view, fetch opportunities in parallel with projects and display them in a tabbed or split layout. On the 'Pipeline' tab, show open opportunities sorted by close date. On the 'Projects' tab, show active projects with percent complete and status. Use the LINKS array on each record to surface connections between them. For creating the opportunity-to-project transition workflow, build an 'Mark as Won' button on opportunity detail views. Clicking it calls update_opportunity_state with state 'WON', then immediately calls create_project with the opportunity name, linked contact, and linked organization (passed in the LINKS array). Show a success state with the new project ID and a link to the project detail view. For client-facing portals, filter projects by the client's organization ID. Insightly project records include LINKS to their associated organizations — query projects and filter by ORGANISATION_ID in the links array to show only the client's projects. For teams using Insightly with detailed task tracking, add a task completion view for each project using the /tasks endpoint filtered by project ID. RapidDev's team can help design complex multi-record dashboards that efficiently batch Insightly API calls for large client lists.
Build a pipeline management page with two tabs: 'Deals' and 'Projects'. Deals tab: fetch open opportunities (action: list_opportunities) and show in a table with name, stage, value, and close date. Add a 'Mark Won' button that calls update_opportunity_state then create_project. Projects tab: fetch active projects (action: list_projects) and show with name, status badge, and a linear progress bar for percent complete.
Paste this in Lovable chat
Pro tip: Insightly's list endpoints return arrays directly (not wrapped in a 'data' key like many other APIs). The response for list_contacts is directly the contacts array, not { contacts: [...] }. Adjust your React component to map over the response directly.
Expected result: The pipeline page shows open opportunities in the Deals tab and active projects in the Projects tab. Marking an opportunity as Won creates a corresponding project in Insightly. The project appears in the Projects tab within seconds.
Common use cases
Client portal showing linked opportunities and project status
Build a client-facing portal in your Lovable app where clients can see their active projects (linked to won opportunities), project milestones, and upcoming deliverables. The Edge Function fetches Insightly projects filtered by the client's organization ID, along with associated task completions and due dates. Clients get real-time project visibility without accessing Insightly directly.
Create an Edge Function called insightly-client that accepts { organizationId } and fetches all active projects linked to that organization from Insightly using INSIGHTLY_API_KEY from secrets. Include project name, status, percent complete, start date, and due date. Then build a client portal page in Lovable showing the client's projects with progress bars and milestone tables.
Copy this prompt to try it in Lovable
Sales and project dashboard for account managers
Create an internal dashboard showing account managers their open opportunities in the sales pipeline alongside active projects for their existing clients. The dashboard gives a complete account view: active deals being pursued, recently won deals in project delivery, and completed projects eligible for renewal opportunities. This single view replaces switching between Insightly's separate CRM and project views.
Create Edge Functions to fetch open Insightly opportunities (filter by OPPORTUNITY_STATE not Won) and active projects (filter by STATUS not Completed) for a specific account manager. Build a split dashboard in Lovable with two columns: Open Deals (opportunity name, stage, value, close date) and Active Projects (project name, status, percent complete). Show totals for pipeline value and active project count.
Copy this prompt to try it in Lovable
Automatic project creation when an opportunity is marked Won
When a sales representative marks an opportunity as Won in your Lovable app, automatically create a linked project in Insightly using the opportunity details as the project template. The project is pre-populated with the client's contact and organization, the contract value, and standard milestone tasks based on the project type. This automates the handoff from sales to delivery without manual data re-entry.
Create an Edge Function called insightly-won-deal that accepts { opportunityId, contactId, organizationId, projectType } and first updates the opportunity OPPORTUNITY_STATE to Won in Insightly, then creates a new Project linked to the opportunity using INSIGHTLY_API_KEY from secrets. Set the project name from the opportunity name, assign the responsible user, and return both the updated opportunity ID and new project ID.
Copy this prompt to try it in Lovable
Troubleshooting
Insightly API returns 401 Unauthorized on all requests
Cause: The Basic Auth encoding is incorrect. Insightly API key auth uses btoa(apiKey + ':') — with a colon and empty password. A common mistake is encoding just the API key without the colon.
Solution: Verify the Authorization header uses btoa(apiKey + ':') — note the colon after the API key with no password following. In the Edge Function, the encoded value should look like: Basic YXBpa2V5OjA= (where YXBpa2V5OjA= is the base64 of 'apikey:' with empty password). Also verify INSIGHTLY_API_KEY is correctly set in Cloud → Secrets.
1// Correct Insightly Basic Auth encoding:2Authorization: `Basic ${btoa(key + ':')}` // colon required, password is emptyAPI returns 404 for organization endpoints
Cause: The endpoint uses the American spelling 'organizations' instead of the Insightly API's UK English spelling 'organisations'.
Solution: Update the Edge Function to use 'organisations' (with 's') for the organizations/companies endpoint. Insightly's API documentation uses UK English throughout. This is the most common endpoint naming mistake for non-UK developers.
1// Correct: UK English spelling in Insightly API2const url = insightlyUrl('organisations') // NOT 'organizations'Contact creation returns 400 with field validation errors
Cause: Required fields are missing or formatted incorrectly. Insightly contact creation requires LAST_NAME at minimum, with FIRST_NAME as optional.
Solution: Ensure LAST_NAME is always provided in contact creation. If you only have a full name, split on the last space character for the last name. Also verify that date fields (CLOSE_DATE, etc.) are in YYYY-MM-DD format — Insightly rejects other date formats.
INSIGHTLY_API_URL returns 404 for all paths
Cause: The regional API URL is incorrect for your account, or the URL includes a trailing path that conflicts with appended endpoint names.
Solution: Verify your API URL from Insightly User Settings → API URL section. Ensure the stored URL ends with 'v3.1/' (trailing slash). For North American accounts the URL is https://api.na1.insightly.com/v3.1/. If you stored the URL without the trailing slash, update the Edge Function to add a slash separator before appending endpoint names.
Best practices
- Always use the API URL from Insightly User Settings rather than constructing it — regional endpoint URLs vary and guessing the wrong region returns 404 for all endpoints.
- Use UK spelling 'organisations' not 'organizations' in Insightly API endpoint paths — this is the single most common endpoint naming mistake.
- Include LINKS array when creating opportunities and projects to establish the CRM-to-project relationship that makes Insightly unique — without links, records are isolated rather than connected.
- Store Insightly contact IDs in your Supabase users table after first creation to avoid repeated email search calls for tag and record update operations.
- Handle null fields gracefully in your React components — Insightly returns many optional fields as null, and rendering null without protection causes empty UI elements.
- Implement the opportunity-to-project transition atomically in one Edge Function invocation — update the opportunity state to Won and create the project in the same function call to ensure both operations succeed together.
- Use pagination ($top and $skip) for all list operations — Insightly's default page size is 100 but accounts with many records require pagination to retrieve complete datasets.
Alternatives
Choose Pipedrive if you need only sales pipeline without project delivery tracking — Pipedrive's visual Kanban pipeline is more refined for pure sales teams.
Choose HubSpot if you need marketing automation alongside CRM and want a more well-known platform with a larger ecosystem — HubSpot's free tier is significantly more generous than Insightly's.
Choose Zoho CRM if you need project delivery alongside CRM and want the broader Zoho ecosystem including Zoho Projects as a native integration — Zoho's suite is more comprehensive than Insightly.
Frequently asked questions
Does Insightly have a free plan that supports API access?
Yes — Insightly's free plan supports 2 users and includes full API access. The free plan includes contacts, organizations, opportunities, projects, and basic task management. For Lovable integrations and development testing, the free plan is sufficient. The Plus plan ($29/user/month) adds email templates, custom fields, workflow automation, and higher API rate limits.
How does Insightly's CRM-to-project linkage work technically?
Insightly links records using a LINKS array on each entity. When creating a project linked to an opportunity, include a LINKS entry with LINK_SUBJECT_TYPE: 'OPPORTUNITY' and LINK_SUBJECT_ID: opportunityId. Similarly, link contacts and organizations to projects. The Insightly UI displays these linked records in the record's detail view, and you can query linked records via GET /opportunities/{id}/links or directly embed linked data in the response.
Why does Insightly use 'organisations' instead of 'organizations'?
Insightly was founded in Australia and uses UK/Australian English spelling in its API. The company name is not affected (you still search for 'organization' in casual conversation), but the API endpoint path is /organisations with the British 's'. Similarly, some field names use UK conventions. This is a well-known gotcha that affects most non-UK developers when building Insightly integrations.
Can I trigger Insightly automation rules from the API?
Insightly's workflow automation (available on Plus plans and above) triggers based on record changes made through the API just as they do through the UI. When you update an opportunity stage or status via the API, any automation rules configured for that field change will fire. This means API-triggered stage moves can create tasks, send emails, or update related records automatically without additional API calls.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation