# Crunchbase

- Tool: FlutterFlow
- Difficulty: Intermediate
- Time required: 45 minutes
- Last updated: July 2026

## TL;DR

Connect FlutterFlow to Crunchbase using a FlutterFlow API Call with Crunchbase's v4 REST API and a user_key credential. There is no free API tier as of 2025 — you need a paid Basic (~$49/mo) or Pro (~$99/mo) plan. Route the user_key through a Firebase Cloud Function proxy so it is not exposed in the compiled app. Use GET for single-entity lookups and POST for organization searches with query filter bodies.

## Build a Company Research and Investor CRM App with FlutterFlow and Crunchbase

Crunchbase is the primary database for startup funding intelligence — company profiles, investor portfolios, funding rounds, acquisitions, and leadership teams. Connecting FlutterFlow to Crunchbase opens up a category of deal-sourcing and investor-CRM apps that were previously possible only on desktop: a mobile app where VCs can look up company funding history on the go, where founders can research potential investors and their portfolio companies, or where sales teams can qualify enterprise prospects by their funding stage and investor backing.

Before diving into the technical setup, there is an important prerequisite to understand: Crunchbase removed its free API tier in 2025. If you are looking for a free trial of the API, it no longer exists — you need a paid subscription to get API access. The Basic plan (check current pricing on crunchbase.com/about/crunchbase-basic-access) gives access to approximately 3 endpoints, while the Pro plan gives fuller access to the organization search endpoint and additional fields. Before you build a single FlutterFlow API Call, verify which endpoints your plan includes — a 403 response that looks like an auth error may actually mean the endpoint is not part of your current plan tier.

Auth is a single user_key credential, used either as a URL query parameter (?user_key=xxx) or as an HTTP header (X-cb-user-key). Since this is a paid credential attached to your billing account, a harvested key means someone else queries Crunchbase on your plan's quota at your expense. For any app beyond a personal demo, route the user_key through a Firebase Cloud Function proxy so it lives server-side, not in the compiled Flutter binary. The Crunchbase v4 API base URL is https://api.crunchbase.com/api/v4.

## Before you start

- A paid Crunchbase subscription with API access — Basic plan (~$49/mo, 3 endpoints) or Pro plan (~$99/mo, full API access); verify current pricing at crunchbase.com
- Your Crunchbase user_key (found in your Crunchbase account settings under API access after subscribing)
- A clear understanding of which endpoints your plan tier includes — check this before building to avoid confusing 403s
- A Firebase project set up for Cloud Functions to host the user_key proxy
- A FlutterFlow project with at least one screen ready to display company or investor data

## Step-by-step guide

### 1. Subscribe to a Crunchbase API plan and get your user_key

Go to crunchbase.com and log in to your account. Navigate to the API section (check your account settings or visit data.crunchbase.com). Crunchbase removed its free API tier in 2025, so you will need to subscribe to a paid plan before you can generate an API key. As of mid-2026, the Basic plan (verify current price on their website) gives access to a limited set of endpoints — approximately 3 entity-type lookups. The Pro plan gives broader access including the organization search endpoint (POST /searches/organizations), which is essential for building a search-driven app. If you subscribe to Basic and try to call the search endpoint, you will get a 403 response that may look like an authentication failure but is actually an entitlement error — your tier does not include that endpoint.

After subscribing, go to your account settings and find the API section. Copy your user_key — it will be a long alphanumeric string. Test it immediately: paste https://api.crunchbase.com/api/v4/entities/organizations/airbnb?user_key=YOUR_KEY into your browser. You should receive a JSON object with Airbnb's Crunchbase organization data. A 401 means your key is wrong. A 403 means the endpoint is not in your plan. An empty or error response means the key has not activated yet (Crunchbase key activation can take a few minutes after subscription). Do not proceed to the next step until this test returns valid JSON.

```
# Test your Crunchbase user_key (replace YOUR_KEY)
curl 'https://api.crunchbase.com/api/v4/entities/organizations/airbnb?user_key=YOUR_KEY'

# Expected: JSON object with organization data including name, short_description, funding_total
# 401: invalid key
# 403: endpoint not in your plan tier
```

**Expected result:** Your Crunchbase user_key is confirmed working via a browser test returning organization JSON for a known company like Airbnb or Stripe.

### 2. Build a Firebase Cloud Function proxy for Crunchbase

The Crunchbase user_key is attached to your paid billing account. If someone extracts it from a compiled FlutterFlow app, they can query Crunchbase against your plan's quota without paying. For any app you distribute, even to a small team, the user_key must live in a Firebase Cloud Function proxy — not in the FlutterFlow API Call configuration that compiles into the app binary.

Deploy the Cloud Function below to your Firebase project. It accepts two types of requests: entity lookups (GET-style, passing a permalink and entity type) and organization searches (POST-style, passing a query body). The function appends the user_key to Crunchbase API requests server-side.

Set the user_key as Firebase environment config (never hardcode it in the function file). Once deployed, your Cloud Function URL becomes the base URL for FlutterFlow — the user_key is completely hidden from the client app.

```
// Firebase Cloud Function: functions/index.js
const functions = require('firebase-functions');
const axios = require('axios');

const USER_KEY = functions.config().crunchbase.user_key;
const CB_BASE = 'https://api.crunchbase.com/api/v4';

exports.crunchbaseProxy = functions.https.onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  if (req.method === 'OPTIONS') {
    res.set('Access-Control-Allow-Methods', 'GET, POST');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    return res.status(204).send('');
  }

  const { action, permalink, entity_type, query_body } = req.body || {};

  try {
    if (action === 'get_entity') {
      // GET /entities/{entity_type}/{permalink}
      const type = entity_type || 'organizations';
      const fields = 'short_description,funding_total,num_funding_rounds,last_funding_type,last_funding_at,founded_on,num_employees_enum,homepage_url,linkedin_url';
      const r = await axios.get(
        `${CB_BASE}/entities/${type}/${permalink}?user_key=${USER_KEY}&field_ids=${fields}`
      );
      return res.json(r.data);
    }

    if (action === 'search_organizations') {
      // POST /searches/organizations
      const body = query_body || { field_ids: ['name', 'short_description', 'funding_total', 'last_funding_type', 'founded_on'], limit: 10 };
      const r = await axios.post(
        `${CB_BASE}/searches/organizations?user_key=${USER_KEY}`,
        body,
        { headers: { 'Content-Type': 'application/json' } }
      );
      return res.json(r.data);
    }

    return res.status(400).json({ error: 'Unknown action. Use get_entity or search_organizations.' });
  } catch (err) {
    const status = err.response?.status || 500;
    return res.status(status).json({ error: err.message, detail: err.response?.data });
  }
});

// Setup:
// firebase functions:config:set crunchbase.user_key="YOUR_USER_KEY"
// firebase deploy --only functions
```

**Expected result:** Your Firebase Cloud Function is deployed and returns Crunchbase organization data when you POST { action: 'get_entity', permalink: 'airbnb', entity_type: 'organizations' } to the function URL.

### 3. Create FlutterFlow API Calls for entity lookup and organization search

Open your FlutterFlow project. Click API Calls in the left navigation. Click + Add → Create API Group. Name it CrunchbaseProxy and set the Base URL to your Firebase Cloud Function URL. Add a Content-Type: application/json header to the group.

Add two API Calls inside the group:

API Call 1 — GetOrganization: Method POST (the proxy uses POST for both actions), endpoint blank. Body: { "action": "get_entity", "permalink": "{{permalink}}", "entity_type": "organizations" }. Add variable: permalink (String). Test with permalink set to 'stripe'. Click Generate JSON Paths. Key paths in the response: $.properties.identifier.value (organization name), $.properties.short_description, $.properties.funding_total.value_usd, $.properties.last_funding_type, $.properties.last_funding_at.value, $.properties.num_funding_rounds, $.properties.founded_on.value, $.properties.num_employees_enum.

API Call 2 — SearchOrganizations: Method POST, endpoint blank. Body: { "action": "search_organizations", "query_body": { "field_ids": ["name", "short_description", "funding_total", "last_funding_type", "founded_on", "num_employees_enum"], "query": [{ "type": "predicate", "field_id": "facet_ids", "operator_id": "includes", "values": ["company"] }], "order": [{ "field_id": "funding_total", "sort": "desc", "nulls": "last" }], "limit": {{limit}}, "after_id": "{{after_id}}" } }. Add variables: limit (Integer, default 10), after_id (String, default ''). Note: the after_id is Crunchbase's cursor for pagination — leave it empty for the first page, then pass the uuid from the last result to get the next page.

```
{
  "group": "CrunchbaseProxy",
  "api_call_1": {
    "name": "GetOrganization",
    "method": "POST",
    "body": {
      "action": "get_entity",
      "permalink": "{{permalink}}",
      "entity_type": "organizations"
    },
    "variables": [
      { "name": "permalink", "type": "String" }
    ],
    "response_paths": [
      "$.properties.identifier.value",
      "$.properties.short_description",
      "$.properties.funding_total.value_usd",
      "$.properties.last_funding_type",
      "$.properties.last_funding_at.value",
      "$.properties.num_funding_rounds",
      "$.properties.founded_on.value",
      "$.properties.num_employees_enum"
    ]
  },
  "api_call_2": {
    "name": "SearchOrganizations",
    "method": "POST",
    "body": {
      "action": "search_organizations",
      "query_body": {
        "field_ids": ["name", "short_description", "funding_total", "last_funding_type", "founded_on"],
        "limit": "{{limit}}",
        "after_id": "{{after_id}}"
      }
    },
    "variables": [
      { "name": "limit", "type": "Integer", "default": 10 },
      { "name": "after_id", "type": "String", "default": "" }
    ]
  }
}
```

**Expected result:** Both API Calls are saved and tested: GetOrganization returns detailed organization data for a known company; SearchOrganizations returns a list of company results for a broad query.

### 4. Build a company search screen with results ListView and detail screen

Open your search screen in FlutterFlow. Add a Column containing a SearchBar TextField at the top, a Button labeled 'Search Crunchbase', and a ListView below. Add Page State variables: searchQuery (String), results (list type), lastUUID (String, default ''), and selectedOrg (dynamic, for the detail screen).

Wire the Search button's action flow to: 1) Set searchQuery Page State to the TextField value, 2) Call SearchOrganizations with a query_body that includes a name predicate filter using the search term (update the proxy function to pass the query through to Crunchbase's search body), 3) Store the returned entities array in the results Page State, 4) Store the uuid from the last result in lastUUID for pagination.

For the ListView child template, create a Card with three widgets: a Text for the company name (bound to the identifier.value from each entity), a Text for short_description with maxLines set to 2 and overflow ellipsis, and a Row at the bottom showing funding_total.value_usd formatted as '$X.XM' and last_funding_type as a badge chip. Tapping the card sets selectedOrg to that entity and navigates to the detail screen.

On the detail screen, add a Column with sections: Company Header (name, logo_url if available), About (short_description), Funding Summary (total_funding, num_funding_rounds, last_funding_type, last_funding_at), and Company Stats (founded_on, num_employees_enum, homepage_url as a tappable link). Wire the screen's Page Load action to call GetOrganization with the selected entity's permalink and populate all these fields from the response.

For pagination, add a 'Load more' Button below the search results ListView. Wire it to re-call SearchOrganizations with after_id set to lastUUID, then append the new results to the existing results Page State list.

**Expected result:** The search screen displays a ListView of Crunchbase organizations matching the search query. Tapping a company navigates to a detail screen with full funding history, employee count range, and founding date.

### 5. Handle 403 plan-tier errors and implement pagination with after_id

Two operational issues commonly appear after the basic integration is working: plan-tier 403 errors and correct cursor-based pagination.

For 403 errors: Crunchbase uses 403 status for two distinct situations — wrong authentication AND endpoint not included in your plan tier. When your Cloud Function returns a 403, read the error detail field in the response body to distinguish between them. If the message mentions 'not authorized for this endpoint' or similar, the fix is upgrading your Crunchbase plan — re-checking your API key will not help. Add an On Error action flow branch in FlutterFlow that reads the error detail and shows an appropriate message: 'Your Crunchbase plan does not include access to this endpoint — please upgrade to Pro for search functionality' for entitlement errors vs 'Invalid API key' for auth errors.

For pagination: Crunchbase's v4 search uses cursor-based pagination rather than page numbers. The search response includes an entities array and a next_page_token (or an after_id in the last entity's uuid). To load the next page, pass after_id equal to the uuid of the last entity in your current results. Pass an empty string (not null) for the first page. In your 'Load more' button's action flow: 1) Read the uuid of the last item in your results Page State, 2) Call SearchOrganizations with after_id set to that uuid, 3) Append new entities to the results Page State using a Custom Action that merges the lists. Display a 'No more results' message when the returned entities array is empty or contains fewer items than the limit.

**Expected result:** The app correctly handles plan-tier 403 errors with a meaningful user message, and the 'Load more' button fetches the next page of search results using Crunchbase's cursor-based after_id pagination.

## Best practices

- Never put your Crunchbase user_key in a FlutterFlow API Call URL, header, or body that ships in the app — it is a paid credential that funds queries against your subscription quota and must stay in a Firebase Cloud Function proxy.
- Verify which endpoints your Crunchbase plan tier includes BEFORE building FlutterFlow API Calls — the Basic and Pro plans include different endpoint sets, and 403 errors for wrong-tier access look identical to auth errors in FlutterFlow.
- Always request only the specific field_ids your app displays in your POST search body — Crunchbase returns all available fields by default, which significantly inflates response sizes on mobile.
- Use Crunchbase's after_id cursor for pagination rather than offset-based pagination — passing after_id as the uuid of the last result in your current list is the correct way to fetch the next page of search results.
- Format funding amounts as human-readable strings ($4.2B, $350M) in your widget bindings rather than displaying raw integers — raw numbers like 4200000000 are not readable in a compact mobile card format.
- Cache frequently-accessed organization detail pages in Firestore — Crunchbase charges per request against your plan quota, and team members looking up the same 10 companies repeatedly wastes quota that could be served from cache.
- Handle null funding data explicitly in your UI — many Crunchbase organizations have undisclosed funding totals, so binding funding_total.value_usd without a null fallback will show blank values for a significant portion of your results.

## Use cases

### Investor deal-sourcing app for VCs and angels

Build a FlutterFlow app where investors can search Crunchbase organizations by industry, location, and funding stage using the POST /searches/organizations endpoint. Each search result card shows company name, one-line description, total funding raised, last funding date, and investor count. Tapping a company opens a detail screen that calls GET /entities/organizations/{permalink} for full funding round history, leadership team, and headquarters location.

Prompt example:

```
A FlutterFlow mobile app for investors to search startups by industry and funding stage, showing company cards with total funding and latest round, with a detail screen for full funding history and team info from Crunchbase.
```

### Founder's investor research CRM

Build a FlutterFlow app where startup founders can search Crunchbase for investors (VCs, angels, corporate VCs) by investment stage and sector focus, view investor portfolio companies, and save promising investors to a shortlist stored in Firestore. The app calls POST /searches/investors with stage and category filters and displays investor profiles with portfolio count, headquarters, and most recent investment date.

Prompt example:

```
A FlutterFlow app for founders to discover and shortlist investors, with search filters for investment stage and sector, showing investor profile cards with portfolio size and most recent deal, backed by Crunchbase API data.
```

### Enterprise sales prospect qualifier app

Build a FlutterFlow tool for enterprise sales teams to quickly qualify prospects by looking up their Crunchbase company profile during a discovery call. The app searches an organization by name, displays funding history and employee count range, and lets the rep add a note and status directly to a CRM record in Firestore — combining Crunchbase's funding intelligence with the team's own deal data in one mobile screen.

Prompt example:

```
A FlutterFlow screen where a sales rep types a company name, sees its Crunchbase funding history and employee range, and can tap to save a qualified or disqualified status note to their Firestore CRM.
```

## Troubleshooting

### Crunchbase API returns 403 Forbidden even though the user_key is correct

Cause: Crunchbase uses 403 for two distinct cases: (1) invalid or unauthorized user_key (auth failure) and (2) the requested endpoint is not included in your current subscription tier. Both return HTTP 403 — the distinction is in the response body error message.

Solution: Check the error detail in the Cloud Function response body. If it mentions endpoint access or entitlement, you need to upgrade your Crunchbase plan — the Basic plan only gives access to approximately 3 endpoints, while the Pro plan is needed for the search endpoint. If the error mentions invalid credentials, regenerate your user_key in your Crunchbase account settings and update the Firebase environment config, then redeploy the function.

### Organization search returns empty entities array even for well-known companies

Cause: The POST /searches/organizations body structure or field_ids array is malformed, causing Crunchbase to return a valid 200 response with zero results rather than an error. This often happens when the query predicate uses wrong operator IDs or field names.

Solution: Test the exact search body directly against the Crunchbase API using curl or Postman to confirm the query syntax before building the FlutterFlow layer. Refer to Crunchbase's API documentation for valid field_id values and operator_id strings (includes, eq, between, etc.). Start with the simplest possible query (no filters, just a field_ids list and a small limit) to confirm the endpoint works, then add filters incrementally.

### Crunchbase funding amounts appear as null in FlutterFlow widget bindings

Cause: Crunchbase's funding_total field is a nested object with value_usd and currency_code sub-fields, not a flat number. The JSON path $.properties.funding_total.value_usd is needed — not $.properties.funding_total. If the company has not disclosed funding or the entity type does not include funding data, the entire funding_total object may be null.

Solution: Use the full nested JSON path $.properties.funding_total.value_usd for the funding amount. Add a null-check in your widget binding with a fallback text like 'Undisclosed' for companies that have not disclosed funding. For the formatted display, use FlutterFlow's number formatting or a custom Dart function to convert the raw USD integer (e.g. 4200000000) to a human-readable string (e.g. '$4.2B').

### Crunchbase API call works in the test tab but returns XMLHttpRequest error in FlutterFlow web Run mode

Cause: Crunchbase's API does not serve CORS headers that allow browser-origin requests from FlutterFlow's web preview domain. The Firebase Cloud Function proxy resolves this by serving the response with Access-Control-Allow-Origin: * headers.

Solution: Ensure all FlutterFlow API Calls target your Firebase Cloud Function URL rather than the Crunchbase API directly. The Cloud Function includes CORS headers in its response, making it compatible with FlutterFlow's web preview. If you see this error, check that your API Group base URL is the Cloud Function URL and not the Crunchbase API URL.

## Frequently asked questions

### Does Crunchbase still have a free API tier in 2025-2026?

No. Crunchbase removed its free API tier in 2025. API access now requires a paid subscription — the Basic plan (verify current pricing at crunchbase.com) gives access to a limited set of entity lookup endpoints, while the Pro plan gives broader access including the organization search endpoint. There is no free trial of the API for new developers.

### What is the difference between Crunchbase Basic and Pro API access?

The Basic plan gives access to approximately 3 entity-type endpoints (organization, person, and funding round detail lookups by permalink). The Pro plan adds the search endpoints (POST /searches/organizations, /searches/investors, etc.) which are necessary for building search-driven FlutterFlow apps. Verify the current plan inclusions on crunchbase.com before subscribing — Crunchbase adjusts plan boundaries periodically.

### Why does Crunchbase use POST for the search endpoint instead of GET?

Crunchbase's v4 search API uses POST because the search query body can be complex — field_ids lists, query predicates with multiple conditions, ordering specifications, and pagination cursors are all passed as a structured JSON body that would be awkward and URL-length-limited as query parameters. This is a common pattern for search-heavy APIs. In FlutterFlow, you model this as a POST API Call with the search body as JSON body variables.

### Can I look up investor profiles and their portfolio companies in FlutterFlow?

Yes, with a Pro plan. The POST /searches/investors endpoint lets you search for investors (venture capital firms, angel investors, corporate VCs) with filters for investment stage, geography, and sector. GET /entities/investors/{permalink} returns an investor's profile including portfolio company list, investment count, and most recent investment date. Wire these to your Cloud Function proxy following the same pattern as organization lookups.

### How does Crunchbase pagination work in FlutterFlow?

Crunchbase v4 uses cursor-based pagination. When you call POST /searches/organizations, the response includes an entities array. To load the next page, take the uuid of the last entity in the current array and pass it as the after_id field in your next search body. Pass an empty string (not null) for after_id on the first page. In FlutterFlow, store the last uuid in a Page State variable after each search call and pass it to the 'Load more' button's API Call action.

---

Source: https://www.rapidevelopers.com/flutterflow-integrations/crunchbase
© RapidDev — https://www.rapidevelopers.com/flutterflow-integrations/crunchbase
