# How to Integrate Retool with Typeform

- Tool: Retool
- Difficulty: Beginner
- Time required: 20 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Typeform using a REST API Resource with a personal access token. Configure Typeform's API credentials in Retool's Resources tab, then build form response management dashboards that view submissions, analyze answers, and manage forms. Use Retool Workflows with Typeform webhooks to process new submissions in real time as they arrive.

## Build a Typeform Response Management Dashboard in Retool

Typeform generates high-quality survey and lead data, but Typeform's native results interface has limitations: you can't build custom analytics across multiple forms, apply complex filters that combine multiple fields, join Typeform responses with your CRM or database records, or trigger automated actions when specific answer combinations are received. Retool connected to Typeform's API solves all of these limitations.

Typeform's REST API v1 exposes forms, responses, and images. The responses endpoint returns a paginated list of submissions with a complex nested structure: each response contains an answers array where each answer object includes a field reference (mapping back to the form's definition), an answer type, and the actual value. Parsing this structure requires matching answer field references against the form's field definitions — a typical pattern for Retool JavaScript transformers.

For real-time response processing, Typeform webhooks deliver each new submission to a URL you specify. Retool Workflows can serve as the webhook endpoint, processing incoming submissions immediately: parsing responses, creating CRM records, sending Slack notifications, writing to databases, or triggering downstream workflows. This combination of pull-based dashboards (Retool REST API queries) and push-based automation (Typeform webhooks → Retool Workflows) gives your team complete control over the Typeform data pipeline.

## Before you start

- A Typeform account with at least one form containing responses
- A Typeform personal access token generated from your Typeform account settings
- The Form ID for each form you want to query (visible in the Typeform URL)
- A Retool account with permission to create Resources and, for webhook processing, permission to create Workflows
- Basic familiarity with Typeform's form builder and response structure

## Step-by-step guide

### 1. Generate a Typeform personal access token

Log into your Typeform account at typeform.com. Click your profile icon in the top right corner and select 'Settings'. In the left navigation of your account settings, click 'Personal tokens' under the Developer section.

Click 'Generate a new token'. Give it a descriptive name like 'Retool Dashboard'. Choose the required scopes: responses:read (to fetch form responses), forms:read (to list forms and their field definitions), and if you need to manage forms or create webhooks from Retool, also include forms:write and webhooks:write.

Click 'Generate token'. Typeform shows the token once — copy it immediately and store it in a password manager or your company's secrets manager. This token authenticates as your Typeform user and has access to all forms and responses you can see.

Note your Form IDs as well. When you open any Typeform form in the editor, the URL contains the form ID: typeform.com/builder/{FORM_ID}/. You'll use this ID in Retool query paths to target specific forms.

**Expected result:** You have a Typeform personal access token with the required scopes. You have noted the Form IDs for forms you want to query.

### 2. Configure the Typeform REST API Resource in Retool

In Retool, navigate to the Resources tab and click 'Create a resource'. Select 'REST API'. Name it 'Typeform API'.

Set the base URL to https://api.typeform.com. All Typeform API paths are relative to this base URL — form queries use /forms/{id}, response queries use /forms/{id}/responses.

For authentication, select 'Bearer Token'. Paste your Typeform personal access token in the token field. Retool will send Authorization: Bearer {token} with every request.

Add a Content-Type header with value application/json. This is needed for any POST requests you make to create webhooks or update forms, and it's good practice to include it on the resource level.

Save the resource. Personal access tokens for Typeform don't expire, so there's no OAuth flow needed. The resource is immediately available.

Store the token in a Retool configuration variable rather than pasting it directly: Settings → Configuration Variables → create TYPEFORM_TOKEN as a secret, then set the Bearer Token field to {{ retoolContext.configVars.TYPEFORM_TOKEN }}. This enables token rotation without updating every Resource.

**Expected result:** The Typeform API resource is configured in Retool with Bearer token authentication. You can now query Typeform's API endpoints directly from Retool queries.

### 3. Build queries to list forms and fetch responses

Create a query named 'getForms' with GET method and path /forms. Add URL parameters: page_size (set to 50) and page (set to 1 for the first page). This returns all forms in your Typeform account with their IDs and titles. Use this to populate a Select dropdown that lets users choose which form to view.

Create a second query 'getFormDefinition' with GET method and path /forms/{{ formSelect.value }}. This returns the complete form structure including all field definitions — you need this to match response answers to their question text. Trigger this query when formSelect changes.

Create a third query 'getFormResponses' with GET method and path /forms/{{ formSelect.value }}/responses. Add URL parameters: page_size (set to 100, the maximum), before (set to {{ responsesTable.pageToken?.before || '' }} for pagination), since (set to {{ dateRangePicker.startDate || '' }} for date filtering), and completed (set to true to show only completed submissions or '' for all).

Run the queries to inspect the response structure. Typeform's responses contain a 'total_items' count, a 'page_count', and a 'items' array. Each item in 'items' is a response object with metadata (landed_at, submitted_at, token) and an 'answers' array.

```
// JavaScript transformer to flatten Typeform responses
const responses = data.items || [];
const formFields = getFormDefinition.data?.fields || [];

// Build a field lookup: field ref/id -> question text
const fieldLookup = {};
formFields.forEach(field => {
  fieldLookup[field.ref] = field.title;
  fieldLookup[field.id] = field.title;
});

return responses.map(response => {
  const flat = {
    responseId: response.token,
    submittedAt: new Date(response.submitted_at).toLocaleString(),
    landedAt: new Date(response.landed_at).toLocaleString(),
    completed: response.calculated?.score !== undefined
  };

  // Flatten all answers by question title
  (response.answers || []).forEach(answer => {
    const questionTitle = fieldLookup[answer.field?.ref] || fieldLookup[answer.field?.id] || answer.field?.ref || 'Unknown';
    
    // Extract value based on answer type
    let value;
    switch (answer.type) {
      case 'text': value = answer.text; break;
      case 'email': value = answer.email; break;
      case 'number': value = answer.number; break;
      case 'choice': value = answer.choice?.label; break;
      case 'choices': value = answer.choices?.labels?.join(', '); break;
      case 'boolean': value = answer.boolean ? 'Yes' : 'No'; break;
      case 'date': value = answer.date; break;
      case 'url': value = answer.url; break;
      case 'file_url': value = answer.file_url; break;
      case 'payment': value = `${answer.payment?.amount} ${answer.payment?.currency}`; break;
      default: value = JSON.stringify(answer[answer.type] || '');
    }
    
    flat[questionTitle] = value || '';
  });

  return flat;
});
```

**Expected result:** The forms list query populates a Select dropdown. Selecting a form loads its responses. The transformer flattens the complex answer structure into a flat object using question titles as keys.

### 4. Build the response management dashboard UI

With data queries working, assemble the dashboard UI. At the top, add a Select component named 'formSelect' populated with {{ getForms.data?.items?.map(f => ({ label: f.title, value: f.id })) || [] }}. This lets users switch between forms.

Below the form selector, add filter controls: a DateRangePicker for filtering by submission date, a TextInput for searching by email or any text field, and a Toggle for 'Completed only'.

Add three Statistic components showing: Total Responses ({{ getFormResponses.data?.total_items || 0 }}), Completed ({{ getFormResponses.data?.items?.filter(r => r.answers?.length > 0).length || 0 }}), and This Week (count of responses submitted in the last 7 days using a JavaScript expression).

Add a Table component bound to {{ getFormResponses_transformer.value || [] }}. The columns depend on your specific form, but common columns include submittedAt, email (or whatever contact field your form collects), and key answer fields. Configure the Table's pagination to 'server-side' mode and connect the page change event to update the before parameter in your getFormResponses query.

Add a Detail Panel that opens when a table row is selected, showing all answer fields for that specific response in a readable format. Include an action area with buttons relevant to your workflow (e.g., 'Create Contact', 'Send to CRM', 'Mark Reviewed').

**Expected result:** The response management dashboard shows a list of Typeform forms, displays responses for the selected form, and provides filtering and detail views. Statistics summarize key response metrics.

### 5. Set up Typeform webhooks with Retool Workflows for real-time processing

For real-time response handling, create a Retool Workflow that receives Typeform webhook notifications. In Retool, navigate to Workflows (in the left sidebar) and click 'Create Workflow'. Name it 'Typeform Response Processor'.

Add a Webhook trigger block. Retool assigns a unique webhook URL — copy this URL. Navigate to the Workflow's settings and configure the webhook to be publicly accessible. The webhook URL format looks like: https://api.retool.com/v1/workflows/{workflowId}/startTrigger.

Next, register this webhook URL in Typeform. Go back to your Typeform form, click 'Connect', then 'Webhooks'. Click 'Add a webhook', paste the Retool workflow webhook URL, and enable it. Optionally enable 'Use a secret' for webhook signature verification.

In your Retool Workflow, add a JavaScript Code block after the trigger. Access the incoming Typeform payload via startTrigger.data. The payload structure mirrors the API response: an event_id, event_type ('form_response'), form_response object with the response token and answers array.

Add Resource Query blocks to your Workflow to process the response: insert into a PostgreSQL database, create a CRM record via another REST Resource, or send a Slack notification. Add error handling blocks to catch and log failures. Publish the Workflow to make the webhook active.

For complex webhook processing workflows with multiple downstream actions and retry logic, RapidDev's team can help design the complete event-driven architecture.

```
// JavaScript Code block in Retool Workflow
// Access Typeform webhook payload from startTrigger.data
const payload = startTrigger.data;
const formResponse = payload.form_response;
const answers = formResponse.answers || [];

// Build field lookup from the response definition
const fieldMap = {};
(formResponse.definition?.fields || []).forEach(field => {
  fieldMap[field.ref] = field.title;
});

// Extract specific answer values by question reference or title
function getAnswerByRef(ref) {
  const answer = answers.find(a => a.field?.ref === ref);
  if (!answer) return null;
  return answer[answer.type] ?? null;
}

// Build a processed record for database insertion
const processedRecord = {
  response_token: formResponse.token,
  form_id: payload.form_id,
  submitted_at: formResponse.submitted_at,
  email: getAnswerByRef('email_field_ref') || answers.find(a => a.type === 'email')?.email,
  name: getAnswerByRef('name_field_ref') || answers.find(a => a.type === 'text')?.text,
  // Add other field extractions specific to your form
};

return processedRecord;
```

**Expected result:** The Retool Workflow is running and receiving Typeform webhooks. New form submissions are processed in real time, with data written to your database and notifications sent. The Workflow shows successful runs in its execution log.

## Best practices

- Store your Typeform personal access token in a Retool configuration variable marked as secret, and reference it in the Resource with {{ retoolContext.configVars.TYPEFORM_TOKEN }} rather than pasting it directly
- Use the opt-in 'completed=true' filter when querying responses to exclude partial submissions — Typeform counts page views as responses, so many response objects have no answers
- Cache the form definition query (getFormDefinition) aggressively — form field structures rarely change and caching avoids the extra API call on every response query load
- Build your response transformer to handle all Typeform answer types (text, email, choice, choices, number, boolean, date, file_url, payment) rather than only the types you see today — forms evolve and new question types may be added
- For webhook-based real-time processing, always validate the Typeform-Signature header in your Workflow to prevent unauthorized payload injection
- Implement response archiving by writing Typeform response data to your own PostgreSQL database via a Retool Workflow — this creates a queryable copy of all responses independent of Typeform's data retention policies
- For multi-form dashboards, use Retool's Select component to switch between forms and add the form's GID to the URL parameter so the form selection persists when users share dashboard links

## Use cases

### Lead form response management dashboard

Build a dashboard for reviewing lead capture form submissions with filtering by submission date, specific answer values, and completion status. Show contact details, form answers in a readable format, and allow the team to tag and categorize leads directly from the Retool interface while syncing status back to your CRM.

Prompt example:

```
Build a Retool app that queries a Typeform lead form's responses. Display a Table with submission date, name, email, company, and key qualifier answers. Add a Date Range filter and a TextInput to search by email. Include a side panel showing the full response for the selected row, with a 'Create CRM Lead' button that writes the data to our Salesforce resource.
```

### Survey analytics dashboard across multiple forms

Build a multi-form analytics view that aggregates responses across several Typeform surveys, shows completion rates, average scores for rating questions, and distribution charts for multiple-choice questions. Give the insights team a custom analytics layer that Typeform's native reports can't provide.

Prompt example:

```
Build a Retool analytics dashboard with a Select input listing all Typeform forms. When a form is selected, show total responses, completion rate, average NPS score (if applicable), and a Bar Chart showing the distribution of answers for each multiple-choice question. Add a date range filter.
```

### Real-time job application processing workflow

Set up a Typeform job application form with a Retool Workflow as the webhook endpoint. When a new application arrives, the Workflow parses the response, writes applicant data to a PostgreSQL database, sends a confirmation email via SendGrid, notifies the hiring manager in Slack, and adds the applicant to a Retool review dashboard — all automatically within seconds of form submission.

Prompt example:

```
Set up a Retool Workflow that receives Typeform webhook payloads for job applications. Extract applicant name, email, role applied for, and uploaded resume URL. Insert into our PostgreSQL applicants table, send a Slack notification to the hiring manager channel, and trigger a SendGrid confirmation email to the applicant. Build a Retool review dashboard showing all applications with status tracking.
```

## Troubleshooting

### Typeform API returns 401 Unauthorized even after pasting the token

Cause: The personal access token may have been entered incorrectly, or the Bearer Token field in the Retool Resource isn't formatted properly.

Solution: Verify the token by copying it from Typeform's account settings again — ensure there are no leading/trailing spaces when pasting. In the Retool Resource, confirm the Authentication type is 'Bearer Token' (not 'API Key' or 'Custom'). Test the token directly by running a simple query to /me endpoint — this should return your Typeform account details if authentication is working.

### The transformer correctly lists answer fields but they all show as 'Unknown' question text

Cause: The getFormDefinition query hasn't run before the response transformer executes, so the fieldLookup object is empty when the transformer tries to match field references.

Solution: Ensure getFormDefinition runs to completion before getFormResponses and its transformer. In Retool, set getFormDefinition to 'Run query automatically' and add it to the queries that execute on formSelect change. Make the getFormResponses query dependent on getFormDefinition by triggering it from getFormDefinition's On Success event handler rather than running independently.

### Typeform webhook payloads arrive at the Retool Workflow but the workflow fails silently

Cause: The Workflow has not been published — changes to Workflows only take effect for webhook triggers after clicking 'Publish release'. Unpublished changes only affect manually triggered test runs.

Solution: After making any changes to the Retool Workflow, click the 'Publish release' button in the top right of the Workflow editor. Published Workflows have a version number and process live webhook payloads. Unpublished drafts are only available for test runs within the editor.

### Response query returns responses but pagination is missing older submissions

Cause: Typeform's response pagination uses cursor-based 'before' and 'after' tokens rather than page numbers. Without implementing cursor handling, only the first 100 responses appear.

Solution: Check the query response for a 'page_count' field — if it's greater than 1, there are more responses. The Typeform API uses the 'token' of the last response as the 'before' cursor for the next page. Store the last response token and pass it as the 'before' parameter in the next query call to load the previous page of results.

## Frequently asked questions

### Why does Typeform's response structure use nested answer objects instead of simple key-value pairs?

Typeform's API is designed to be form-structure-agnostic — each answer references its parent field by ID/ref rather than by a human-readable name. This allows the same API to handle forms with any combination of question types. The tradeoff is that displaying answers with question text requires fetching the form definition separately to build a lookup table. Once you have the form definition cached, the matching is straightforward in a JavaScript transformer.

### Can I export Typeform responses to a database using Retool automatically?

Yes, use a Retool Workflow with two approaches: (1) A Webhook trigger that fires when each new response is submitted — processes and inserts into your database in real time, or (2) A scheduled trigger that runs every hour/day and queries the Typeform API for responses submitted since the last run, then bulk-inserts new ones. The webhook approach is more efficient for busy forms; the scheduled approach is simpler and more resilient to temporary failures.

### Does Retool's Typeform integration support file upload responses?

Yes. When a Typeform question includes a file upload field, the response answer contains a file_url field with a time-limited URL to the uploaded file. You can display this URL in your Retool dashboard as a downloadable link. Note that Typeform file URLs expire after a period — if you need permanent access to uploaded files, download and store them to your own S3/storage bucket via a Retool Workflow when processing responses.

### How does Retool's Typeform integration compare to Typeform's native integrations like Google Sheets or Zapier?

Retool's Typeform integration gives you full programmatic control over response data — you can filter, join with other data sources, build custom analytics, and create complex automation logic. Native Typeform integrations (Google Sheets, Mailchimp, HubSpot) offer simpler one-directional data pushes without the ability to combine Typeform data with other sources or build conditional logic. Use Retool when you need custom dashboards or multi-system workflows; use native integrations for simple one-to-one data forwarding.

---

Source: https://www.rapidevelopers.com/retool-integrations/typeform
© RapidDev — https://www.rapidevelopers.com/retool-integrations/typeform
