Back to docs
API Reference

Sync Koji Customer Interviews to HubSpot: Live Insights on Every Contact

Push Koji interview transcripts, themes, and quality scores onto HubSpot contact and company records using the Koji API and the HubSpot API.

HubSpot is where most go-to-market teams already live. Sales reps work deals there, CS managers track health scores there, marketers route nurture sequences there. The problem: the qualitative customer evidence that should inform every one of those workflows usually sits in a separate research tool — or a long-forgotten Notion doc.

This guide shows you how to bridge that gap by piping Koji's AI-moderated interview output directly into HubSpot. Within an hour you can have every CSAT call, churn interview, and onboarding feedback session land on the matching HubSpot contact, complete with the verbatim quote, the AI-extracted themes, the quality score and a short summary.

What You Will Build

By the end of this guide, your stack will look like this:

  1. You start a Koji interview for a HubSpot contact through the API, passing the contact's email as the respondent's external id, and the participant completes it (voice or text).
  2. Koji runs analysis, scores quality, extracts themes and a structured summary.
  3. Your scheduled job checks each interview id it started against the Koji read endpoint and picks up the finished ones. Koji does not send outbound webhooks yet.
  4. Your job uses that email to find the HubSpot contact and writes the insight to custom properties on the contact (and optionally the associated company).
  5. HubSpot workflows can now route, alert, or filter on those properties — for example, auto-paging the CSM when a high-value account drops a churn signal.

The whole pattern works with the Koji API polling documented in Webhook Setup and the standard HubSpot CRM API.

Why This Beats the Default

Most teams collect feedback in a survey tool, paste a CSV into HubSpot once a quarter, and call it integrated. That has three failure modes:

  • Latency. A churn signal from a Tuesday interview lands in HubSpot the following month — far too late to save the account.
  • Loss of context. A 5-point CSAT score is dumped onto the contact, but the verbatim explanation never makes it across.
  • No structured signal. Free-text feedback cannot be filtered, segmented, or used as a workflow trigger.

Koji solves all three. Analysis runs as soon as the interview ends, so your next poll picks it up. The read endpoint returns the verbatim quote, the theme tags, and the structured answers from all six question types — open_ended, scale, single_choice, multiple_choice, ranking, and yes_no. See Structured Questions in AI Interviews for a primer on how those become first-class HubSpot fields you can filter on.

Prerequisites

  • A Koji API key with the interview:start and interview:read permissions. API access comes with the Interviews and Enterprise plans (see API Authentication).
  • A HubSpot account with API access — Operations Hub Starter is the cheapest tier that supports custom-coded workflow actions, but the integration also works with a Private App on the free CRM tier.
  • A HubSpot Private App access token. Create one in Settings → Integrations → Private Apps with the crm.objects.contacts.write, crm.schemas.contacts.write, and crm.objects.companies.write scopes.
  • A small forwarder. You can use a serverless function (Vercel, Cloudflare Workers, AWS Lambda), an existing backend route, or a no-code tool like Zapier or Make. Examples below use Node 20 on Vercel.

Step 1: Create Custom Properties in HubSpot

Before any data flows in, create a home for it. In Settings → Properties → Contact properties, add the following four custom properties:

Property nameInternal nameTypeNotes
Latest Interview Quotekoji_latest_quoteMulti-line textThe most representative verbatim
Latest Interview Themeskoji_latest_themesMulti-line textComma-separated tags
Interview Quality Scorekoji_quality_scoreNumber1 to 5
Latest Interview Summarykoji_latest_summaryMulti-line textThe AI summary of the interview

You can mirror the same four properties at the company level if you want account-wide rollups.

Step 2: Build the Forwarder

The forwarder fetches each interview you started, waits until it is finished and analysed, looks up the HubSpot contact by the email you passed as the external id, and PATCHes the four custom properties. Here is a Vercel-style handler you run on a schedule:

// /api/koji-to-hubspot.js
// Run this on a schedule (Vercel cron, GitHub Action, any cron).
// Koji has no outbound webhooks yet, so the job pulls from Koji.
// pendingIds are the interview ids you saved when you started each
// interview with POST /api/v1/interviews/start, passing the contact
// email as respondent.external_id.

const KOJI_API_KEY = process.env.KOJI_API_KEY
const HUBSPOT_TOKEN = process.env.HUBSPOT_PRIVATE_APP_TOKEN
const FINISHED = ['completed', 'partial', 'abandoned']

// Analysis items can be plain strings or objects with a text field
const text = (item) => (typeof item === 'string' ? item : item?.text)

export default async function handler(req, res) {
  const pendingIds = await loadPendingIds() // from your own store

  for (const id of pendingIds) {
    // 1. Fetch the interview from Koji
    const r = await fetch(`https://www.koji.so/api/v1/interviews/${id}`, {
      headers: { Authorization: `Bearer ${KOJI_API_KEY}` },
    })
    if (!r.ok) continue
    const interview = await r.json()

    // analysis stays null until the interview has ended and been analysed
    if (!FINISHED.includes(interview.status) || !interview.analysis) continue

    const email = interview.respondent?.external_id
    if (!email) {
      await markDone(id) // nothing to match on
      continue
    }

    // 2. Look up the HubSpot contact by email
    const lookup = await fetch(
      `https://api.hubapi.com/crm/v3/objects/contacts/${encodeURIComponent(email)}?idProperty=email`,
      { headers: { Authorization: `Bearer ${HUBSPOT_TOKEN}` } }
    )
    if (lookup.status === 404) {
      await markDone(id) // skip unknown contacts
      continue
    }
    const contact = await lookup.json()
    const { analysis } = interview

    // 3. Patch custom properties
    await fetch(`https://api.hubapi.com/crm/v3/objects/contacts/${contact.id}`, {
      method: 'PATCH',
      headers: {
        Authorization: `Bearer ${HUBSPOT_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        properties: {
          koji_latest_quote: text(analysis.extractedData?.quotes?.[0]) ?? analysis.summary,
          koji_latest_themes: (analysis.themeTags ?? []).map(text).join(', '),
          koji_quality_score: analysis.qualityScore?.score,
          koji_latest_summary: analysis.summary,
        },
      }),
    })

    await markDone(id) // take it off the pending list
  }

  return res.status(200).json({ ok: true })
}

Deploy the function and copy its public URL.

Step 3: Schedule the Forwarder

There is nothing to register inside Koji, because Koji has no outbound webhooks. Run the forwarder on a schedule instead: a Vercel cron, a GitHub Action, or any cron you already have. Give it a Koji API key and a small store of interview ids that are still waiting, and remove each id once it is written so nothing is written twice. The API reads interviews by id, so this pattern covers the interviews you start through the API rather than ones people take through a shared interview link.

Run a quick end to end test with one real interview and check that the contact's custom properties update inside HubSpot. The write lands on the next run, so pick an interval that matches how fast you need the signal.

Step 4: Trigger HubSpot Workflows on the New Data

This is where the integration earns its keep. A few patterns to copy:

  • Churn alert. Create a workflow filtered on koji_latest_themes contains "cancel" and Lifecycle stage = Customer. Action: notify the CSM and create a high-priority task. Pair with Churned Customer Interviews for the upstream interview design.
  • Save-the-deal hand-off. Filter on koji_quality_score >= 4 and themes contains "pricing". Action: create a Slack message to the AE owning the deal. Combine with Pricing Research Interviews for inspiration on which questions to ask.
  • Onboarding intervention. Filter new customers whose first-week interview surfaced "confused" or "stuck". Action: enroll into a high-touch onboarding sequence.
  • Account-level rollups. Use a HubSpot Custom Coded Workflow Action to aggregate the most common themes across all contacts in the same company, then write the result to a company property like koji_account_top_theme.

No-Code Alternative: Zapier or Make

If you prefer not to maintain a serverless function, the same flow works through Zapier:

  1. Trigger: Schedule by Zapier, then a step that fetches each stored interview id from the Koji interview endpoint. Koji cannot call Zapier, so Zapier polls Koji.
  2. Filter: Only continue for interviews that are analysed and that the Zap has not already written.
  3. Search: HubSpot — Find Contact (search by email).
  4. Action: HubSpot — Update Contact, mapping the four properties above.

Make.com and n8n follow the same pattern. Latency rises slightly (10–30 seconds depending on plan) but the integration takes 10 minutes to assemble end-to-end. The shared design language with Send Research Insights to Slack means you can fork the same Zap and point it at HubSpot.

Anonymous Mode and PII

If you start an interview without an external id, the read endpoint returns respondent.external_id as null. The forwarder above skips those interviews silently, which is the correct behaviour: there is no contact to enrich, so no HubSpot write happens. For mixed studies (some respondents identified, some anonymous), the integration handles both cases without configuration.

Keeping the Forwarder Honest

Because the forwarder pulls from Koji instead of accepting a push, there is no public endpoint for anyone to guess and no signature to verify. Keep the Koji API key and the HubSpot token in server side environment variables, remove each interview id from your pending list once you have written it so a retry cannot double write, and log every write. The same patterns are covered in Research Automation: Building Real-Time Pipelines.

What Competitors Cannot Match

Survey tools like SurveyMonkey or Typeform can push raw answers into HubSpot — but they push raw text. Without the AI moderator that Koji runs on every interview, you do not get themes, you do not get quality scores, and you do not get an extracted verbatim. The HubSpot field becomes "the user typed idk" instead of "the user's #1 reason for cancelling was unclear pricing on annual plans."

The combination of Koji's AI-moderated probing and HubSpot's workflow engine turns research from a quarterly readout into a real-time GTM signal. That is the integration RevOps teams have been building manually for years; with Koji it is an evening of work.

Related Resources

Further reading on the blog

<!-- further-reading:blog -->

Related Articles

Amplitude + Koji: Trigger AI Interviews from Product Analytics and Pipe Insights Back as Events

How to close the loop between Amplitude product analytics and Koji AI interviews — fire interview links to users in specific Amplitude cohorts, and pipe interview themes, sentiment, and quality scores back into Amplitude as user properties and custom events.

API Authentication

How Koji Headless API authentication works: pk_live_ API keys, permissions, session tokens, and origin allowlists.

Attio + Koji: Launch AI Interviews from Your CRM and Sync Every Insight Back to the Record

Connect Attio to Koji to trigger AI customer interviews from CRM records and lists, then write themes, quotes, and structured scores back onto each contact and company automatically.

Calendly + Koji: Auto-Run AI Interviews After Every Demo, Call, and No-Show

Connect Calendly to Koji to trigger AI voice and text interviews from meeting events — post-demo, post-onboarding, and no-show follow-ups — and capture structured feedback automatically.

Churned Customer Interviews: How to Talk to Users Who Left (and Win Them Back)

Learn how to conduct churned customer interviews that reveal why users really left — and how AI-moderated interviews make it scalable. Includes questions, structure, and templates.

How to Use Your CRM Data for Targeted AI Research: Import Participants and Personalize Every Interview

Your CRM already contains your best research sample. Learn how to export customer segments, import them into Koji, and invite each person with a personal link, either by Koji email with reminders and tracking or from your own CRM.

Google Sheets + Koji: Launch AI Interviews from a Spreadsheet and Auto-Log Every Insight Back

Turn a Google Sheet of contacts into a batch of Koji AI interviews, and auto-append every completed interview's themes, sentiment, quality score, and transcript link back to a live results tab — no data stack required.

Headless API Overview

Manage interviews programmatically with the Koji REST API — start, message, and complete interviews from your own code.

Intercom + Koji: Run Deep AI Interviews From Your Support and Messaging Workflows

Trigger Koji AI-moderated interviews from Intercom conversations, post-resolution surveys, and outbound messages — then sync themes, sentiment, and quality scores back as Intercom user attributes.

Send Koji Insights to Linear: Auto-File Engineering Tickets from Customer Interviews

Wire Koji to Linear so every customer interview that surfaces a real pain point auto-creates a tagged Linear issue — with verbatim quote, theme, study link, and quality score attached. Replace the Slack-thread-to-screenshot-to-ticket workflow with a Zapier schedule that polls the Koji API.

Connect Koji to Make (Make.com): Build No-Code Customer Research Automations

Use Make (formerly Integromat) scenarios to trigger Koji AI interviews from any app and route themes, sentiment, and transcripts to Slack, Notion, your CRM, or a spreadsheet, no code, using HTTP and Schedule modules.

Mixpanel + Koji: Trigger AI Interviews from Product Events and Pipe Insights Back as Properties

Trigger Koji AI-moderated interviews from Mixpanel cohorts and behavior, then pipe themes, sentiment, and quality scores back into Mixpanel as events and user profile properties.

Sync Koji Research Insights to Notion: Build a Self-Updating Research Repository

Connect Koji to Notion via Zapier (or the API) so every completed AI interview becomes a fresh Notion page — with transcript, structured answers, themes, quality score, and AI summary attached. Build a research repository that updates itself.

Pipedrive + Koji: Turn Deal Stages into AI Win-Loss and Post-Demo Interviews

Connect Pipedrive to Koji to trigger AI voice and text interviews when deals are won, lost, or move stage, then sync themes and structured scores back to Pipedrive deal fields for a continuous win-loss program.

Pricing Research Interviews: How to Understand What Customers Will Pay

Discover how to run qualitative pricing research interviews that reveal willingness to pay, price anchors, and the emotional logic behind buying decisions — beyond what surveys can surface.

Real-Time Research Insights: How to See Themes, Quotes, and Quality Scores as Interviews Complete

Stop waiting weeks for analysis — modern AI research platforms surface themes, structured-question distributions, sentiment, and quality-scored quotes the moment each interview ends. Here is how real-time research insights work in Koji and how to design studies that take advantage of them.

Research Automation: How to Build Real-Time Research Pipelines with Webhooks

Build automated research pipelines on the Koji API today: event-triggered interviews, completion detection, and insight routing, no native webhooks required.

Sync Koji AI Interviews to Salesforce: Customer Insights on Every Account, Contact, and Opportunity

Push interview transcripts, AI themes, sentiment, and quality scores from Koji into Salesforce with a scheduled worker on the Koji read API and the Salesforce REST API — so account executives, customer success managers, and revenue ops teams act on customer evidence inside the CRM they already live in.

Segment + Koji: Trigger AI Interviews from CDP Audiences and Sync Insights Back as Traits

Use Segment Audiences and events to trigger Koji AI-moderated interviews, then pipe summaries, key insights and sentiment back into Segment as track events and user traits that fan out to every downstream tool.

Send Research Insights to Slack: Real-Time Customer Interview Notifications via Webhooks

Get customer interview insights from Koji into your Slack workspace. There is no native Slack app and Koji has no outbound webhooks, so you either paste the study's public report link into a channel, or have your own backend, Zapier, n8n or Make poll the Koji read API and post to a Slack incoming webhook. Step-by-step setup with a working recipe.

Structured Questions in AI Interviews

Mix quantitative data collection — scales, ratings, multiple choice, ranking — with AI-powered conversational follow-up in a single interview.

Webhook Setup

Koji has no native outbound webhooks yet. Three working alternatives: polling the read endpoint, embed completion events, and automation platforms.

Connect Koji to Zapier: Automate Customer Research Workflows in Minutes

Route every completed AI customer interview from Koji into 6,000+ Zapier apps — including Notion, Linear, Salesforce, Airtable, and Gmail. A step-by-step integration guide.

Zendesk + Koji: Trigger AI Interviews from Support Tickets and Sync Insights Back to Every Conversation

Use Zendesk triggers to invite customers to Koji AI-moderated interviews from solved tickets, low CSAT, or specific tags, tie each interview to its ticket through the headless API, and have a small scheduled worker post themes, sentiment, and a response link back onto the ticket.