# How to Integrate Retool with Thinkific

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

## TL;DR

Connect Retool to Thinkific using a REST API Resource with your API key and subdomain configured in the base URL and headers. Build online school admin panels that manage courses, track student enrollments, monitor completion rates, and analyze order revenue — providing operations teams with a custom dashboard that combines Thinkific data in ways the native admin panel does not support.

## Build a Custom Online School Operations Dashboard on Top of Thinkific

Thinkific's admin interface is designed for individual course creators and provides solid tools for content management, but it shows its limits when operations teams need portfolio-level views, cross-course student analytics, or custom reporting that combines enrollment data with external business metrics. Building reports across twenty courses means twenty separate Thinkific admin page visits — a workflow that does not scale for growing online schools. Retool connects directly to Thinkific's REST API and enables purpose-built operational dashboards that surface exactly the data your team needs in one view.

Thinkific's API uses an API key plus subdomain authentication model. You generate an API key in your school settings, configure it as a custom header in Retool's REST API Resource, and specify your school's unique subdomain in a separate header. This combination authenticates every request to Thinkific's API servers without any OAuth flow. All data surfaces — courses, users (students and instructors), enrollments, orders, bundles, and promotions — are accessible through GET requests that return paginated JSON arrays, easily consumable by Retool's query editor and component system.

For online education businesses with significant course catalogs, the value of this integration compounds quickly. A single Retool dashboard can show completion rates trending by week, identify students who have been enrolled for over 30 days without starting the course, surface courses with unexpectedly high drop-off rates, and combine Thinkific order data with payment processor records for reconciliation. These are views that take hours to construct manually from Thinkific's native reports but are available instantly once the Retool dashboard is built.

## Before you start

- A Thinkific account with at least one published course and existing student data
- Thinkific Basic plan or higher (API access requires a paid plan)
- Your Thinkific school subdomain (the part before .thinkific.com in your school URL)
- A Thinkific API key generated from Settings → Code & API → API in your school admin
- A Retool account (Cloud or self-hosted) with permission to create Resources

## Step-by-step guide

### 1. Generate a Thinkific API key and find your subdomain

Before configuring Retool, gather two pieces of information from your Thinkific school: your API key and your subdomain. Sign in to your Thinkific school admin panel. To find your subdomain, look at your browser's address bar — your Thinkific admin URL is in the format yourschool.thinkific.com/admin. The subdomain is the 'yourschool' portion before .thinkific.com. Write this down as you will need it for the Resource header configuration. To generate an API key, navigate to Settings in the left sidebar of your Thinkific admin panel. Click 'Code & API' or look for an 'API' tab in settings — the location varies slightly depending on your Thinkific plan. On the API settings page, you will find your API key displayed or a 'Reveal' button to show it. Copy the API key value. If no API key exists yet, look for a 'Generate' or 'Regenerate' button. Thinkific provides a single API key per school account — it is not possible to create multiple keys with different scopes. The API key provides full read and write access to your school's data, so treat it with the same security as a password. Store it temporarily somewhere safe — you will paste it into Retool's Resource configuration in the next step. Note that Thinkific API keys do not expire unless explicitly regenerated, but if you regenerate the key, you must update it in Retool immediately to avoid API authentication failures.

**Expected result:** Your Thinkific API key is copied and your school subdomain is noted. Both values are ready to configure in the Retool REST API Resource.

### 2. Create a REST API Resource with Thinkific headers

In Retool, navigate to the Resources tab from your organization's homepage sidebar. Click '+ Create new', scroll through the connector list, and select 'REST API'. Set the Name to 'Thinkific API'. Set the Base URL to https://api.thinkific.com — this is Thinkific's central API host, not your school-specific URL. For Authentication, select 'No authentication' from the dropdown — Thinkific uses custom headers rather than the standard Bearer token or Basic auth schemes that Retool's built-in auth options cover. In the Headers section, click 'Add header' three times to add the required headers. First, add X-Auth-API-Key with your Thinkific API key as the value. Second, add X-Auth-Subdomain with your school subdomain as the value (e.g., yourschool, not the full yourschool.thinkific.com domain). Third, add Content-Type with value application/json. These three headers are required on every Thinkific API request — the API key authenticates you, the subdomain routes the request to your school, and the content type ensures JSON encoding. Click 'Test connection'. Thinkific's root API endpoint may return a 404 since there is no base path, but if the network request reaches Thinkific without a DNS or connectivity error, the resource is configured correctly. Click 'Save resource'.

**Expected result:** A REST API Resource named 'Thinkific API' is saved with the X-Auth-API-Key, X-Auth-Subdomain, and Content-Type headers configured. The resource is available in the query editor for all apps in your Retool organization.

### 3. Query courses and enrollments

Open a Retool app and navigate to the Code panel at the bottom. Click '+ New query', select your Thinkific API resource, and name the query getCourses. Set the Method to GET and the URL path to /api/v1/courses. Add URL parameters: set page to 1 and limit to 50 (Thinkific's maximum per-page response). Click 'Run query'. Thinkific returns a JSON object with a items array containing course objects and a meta object with pagination info (total_count, next_page, previous_page). Each course in the items array has fields including id, name, slug, description, price, course_card_image_url, duration, and status ('published' or 'draft'). Create a transformer that filters to only published courses and extracts the fields you need for display. Bind the transformed output to a Table component by dragging a Table onto the canvas and setting Data source to {{ getCourses.data }}. To get enrollment data, create a second query named getEnrollments with path /api/v1/enrollments. Add parameters including page, limit (50), and course_id set to {{ coursesTable.selectedRow.id }} to filter enrollments for the selected course. The enrollments response includes user data (id, email, first_name, last_name) and enrollment metadata (activated_at, completed_at, percentage_completed, is_free_trial, created_at, and updated_at for the last activity timestamp).

```
// Transformer: flatten Thinkific courses response
const courses = data.items || [];
return courses
  .filter(c => c.status === 'published')
  .map(c => ({
    id: c.id,
    name: c.name,
    slug: c.slug,
    price: c.price ? `$${(c.price / 100).toFixed(2)}` : 'Free',
    status: c.status,
    duration: c.duration || 'N/A'
  }));
```

**Expected result:** The getCourses query returns published courses in a Table. Clicking a course row triggers getEnrollments and shows all enrolled students for that course in a second Table below.

### 4. Calculate student completion metrics with transformers

Thinkific's enrollments endpoint returns raw completion data that needs transformation to be useful for dashboards. Each enrollment includes percentage_completed (a number 0-100), activated_at (when the student first accessed the course), completed_at (null if not finished), and updated_at (the last time any enrollment record was modified, which approximates last activity). Create a JavaScript query named enrollmentMetrics that processes the getEnrollments response and calculates per-enrollment derived fields for display. The transformer should calculate: days since enrollment (from created_at to today), days since last activity (from updated_at to today), enrollment status classification ('Completed' when completed_at is not null, 'Active' when updated within 14 days, 'At Risk' when updated 14-30 days ago, 'Inactive' when updated over 30 days ago), and format the percentage_completed as a display string. Also create a summary statistics query named courseSummary using the same data to calculate overall completion rate (enrollments with completed_at not null / total enrollments × 100), average completion percentage across all enrollments, count of active students, and count of at-risk students. Display summary statistics in Stat components above the enrollments Table, and use the status classification in the Table to color-code rows: green for Completed, blue for Active, yellow for At Risk, red for Inactive.

```
// Transform enrollments with derived activity and status fields
const enrollments = getEnrollments.data?.items || [];
const today = new Date();

return enrollments.map(e => {
  const enrolledAt = e.created_at ? new Date(e.created_at) : null;
  const lastActivity = e.updated_at ? new Date(e.updated_at) : null;
  const daysEnrolled = enrolledAt ? Math.floor((today - enrolledAt) / (1000 * 60 * 60 * 24)) : null;
  const daysSinceActivity = lastActivity ? Math.floor((today - lastActivity) / (1000 * 60 * 60 * 24)) : null;

  const status = e.completed_at ? 'Completed'
    : daysSinceActivity === null ? 'Unknown'
    : daysSinceActivity <= 14 ? 'Active'
    : daysSinceActivity <= 30 ? 'At Risk'
    : 'Inactive';

  return {
    student_name: `${e.user?.first_name || ''} ${e.user?.last_name || ''}`.trim() || 'N/A',
    email: e.user?.email || 'N/A',
    enrolled_at: enrolledAt ? enrolledAt.toLocaleDateString() : 'N/A',
    completion_pct: `${Math.round(e.percentage_completed || 0)}%`,
    status,
    days_enrolled: daysEnrolled ?? 'N/A',
    days_since_activity: daysSinceActivity ?? 'N/A',
    completed: e.completed_at ? new Date(e.completed_at).toLocaleDateString() : null
  };
});
```

**Expected result:** The enrollment Table shows students with color-coded status badges (Active, At Risk, Inactive, Completed), days since activity, and completion percentage. Stat components above the table display total enrolled, active, at-risk, and completed counts.

### 5. Build an order management and revenue panel

To build revenue visibility into your Thinkific dashboard, create queries for the orders endpoint. Create a query named getOrders with Method GET and path /api/v1/orders. Add URL parameters to filter by date range using created_at[gte] and created_at[lte] bound to a DateRangePicker component in your app — for example, set created_at[gte] to {{ dateRange.start }} and created_at[lte] to {{ dateRange.end }}. Also set limit to 50 and page for pagination. The orders response includes user information, amount_in_cents (the amount charged in cents), created_at, status ('complete', 'pending', or 'refunded'), coupon_id, and a course or bundle reference. Create a JavaScript transformer named orderSummary that aggregates the orders response: sum amount_in_cents for all complete orders and convert to dollars, count of complete orders, count of refunded orders, and calculate the refund rate as a percentage. Display these as Stat components: Gross Revenue, Orders Completed, Refund Rate. A Table below shows all individual orders with student name, email, course name, amount paid, coupon code if any, and status. Add a DateRangePicker component linked to the getOrders query's date parameters so finance staff can review any billing period on demand. For complex Thinkific deployments integrating with payment processors, CRM systems, and accounting tools for automated revenue reporting, RapidDev's team can help architect the complete Retool solution.

```
// Calculate order revenue summary
const orders = getOrders.data?.items || [];

const completedOrders = orders.filter(o => o.status === 'complete');
const refundedOrders = orders.filter(o => o.status === 'refunded');

const grossRevenue = completedOrders.reduce((sum, o) => sum + (o.amount_in_cents || 0), 0);
const refundAmount = refundedOrders.reduce((sum, o) => sum + (o.amount_in_cents || 0), 0);

return {
  gross_revenue: `$${(grossRevenue / 100).toFixed(2)}`,
  net_revenue: `$${((grossRevenue - refundAmount) / 100).toFixed(2)}`,
  completed_orders: completedOrders.length,
  refunded_orders: refundedOrders.length,
  refund_rate: orders.length > 0
    ? `${Math.round((refundedOrders.length / orders.length) * 100)}%`
    : '0%'
};
```

**Expected result:** The revenue panel shows Gross Revenue, Net Revenue, and Refund Rate Stat components that update when the DateRangePicker values change. The orders Table below shows individual transactions with student details, course name, amount, and status.

## Best practices

- Store the Thinkific API key as a secret configuration variable in Retool (Settings → Configuration Variables, marked as secret) and reference it in the Resource header as {{ retoolContext.configVars.THINKIFIC_API_KEY }} — never paste the key value directly in a Resource header that non-admin Retool users can view.
- Both the X-Auth-API-Key and X-Auth-Subdomain headers must be present on every Thinkific API request. Configure them in the Resource's global headers section so they are automatically included in all queries without adding them per-query.
- Thinkific returns prices in the smallest currency unit (cents). Always divide by 100 before displaying dollar amounts in Stat components or Table columns — this is the most common data formatting error in Thinkific integrations.
- Use Thinkific's pagination parameters (page and limit) with Retool Table's built-in pagination feature for courses and enrollments — schools with large student databases will return incomplete data if pagination is not implemented.
- Add enrollment status classification in your transformer (Active, At Risk, Inactive) using updated_at as a proxy for last activity — this derived field enables proactive student success interventions that Thinkific's native reporting does not surface.
- For dashboards accessed by multiple team members (student success managers, finance staff, content managers), use Retool's permission system to restrict write operations (enrollment creation, order management) to authorized roles while allowing read-only access for reporting users.
- Build a separate Retool Workflow with a weekly Schedule trigger that calculates at-risk student counts per course and sends a summary email to student success managers — this proactive reporting layer reduces the need for manual dashboard checks.

## Use cases

### Build a school-wide course performance overview

Your online school has twenty-five courses and you need a dashboard showing total enrollment, active students (enrolled within the last 30 days), average completion rate, and total revenue generated for each course — sorted by revenue to identify your top performers. Thinkific's admin shows this data per course with no cross-course comparison view. The Retool app queries courses, enriches each with enrollment and order counts, and displays everything in a sortable Table with an inline bar chart for revenue comparison.

Prompt example:

```
Build a course performance dashboard that lists all Thinkific courses with their name, enrollment count, active student count (enrolled in last 30 days), completion rate, and total revenue. Add a bar chart showing revenue per course sorted descending. Include a search bar and a category filter dropdown.
```

### Create a student lifecycle management panel

Your student success team needs to identify at-risk learners: students enrolled in any course who have not logged in for more than 14 days and have completion rates below 30%. Finding these students in Thinkific requires manual filtering across each course. The Retool app queries all enrollments across all courses, joins them with user data, calculates days since last activity from the updated_at timestamp, and presents a filtered table of at-risk students with their email for outreach campaigns.

Prompt example:

```
Build a student risk panel that queries all Thinkific enrollments, joins with user data to get student email and name, calculates days since last activity, and filters for students with completion percentage below 30% and last activity more than 14 days ago. Show results in a Table with student email, course name, completion rate, and days inactive. Include a 'Copy emails' button.
```

### Build an order and revenue reconciliation dashboard

Your finance team processes monthly revenue reports and needs to reconcile Thinkific orders with your accounting system. They need a view of all orders within a billing period showing course purchased, price paid, coupon applied, and payment status — filterable by date range and exportable. Thinkific's native order history view does not support custom date range filters or bulk data review. The Retool app builds this using Thinkific's orders endpoint with date parameters bound to DateRangePicker components.

Prompt example:

```
Build a revenue reconciliation panel with date range pickers that query Thinkific orders for a selected period. Show each order's student name, email, course or bundle purchased, full price, amount paid after discount, coupon code, and payment provider. Calculate and display total gross revenue, total discount, and net revenue as Stat components above the Table.
```

## Troubleshooting

### Query returns 401 Unauthorized

Cause: The X-Auth-API-Key header is missing, incorrect, or the API key has been regenerated in Thinkific since it was configured in Retool. The X-Auth-Subdomain header may also be missing or use the wrong format.

Solution: Navigate to your Thinkific school admin, go to Settings → Code & API → API, and verify the API key matches what is in your Retool Resource. Also confirm the X-Auth-Subdomain header contains only the subdomain portion of your school URL (e.g., 'yourschool', not 'yourschool.thinkific.com'). Edit the Retool Resource to update both headers: Resources tab → select Thinkific API → edit headers → Save.

### Enrollment percentage_completed shows 0 for all students despite course activity

Cause: The percentage_completed field in Thinkific represents the percentage of lessons marked complete by the student, not the percentage of lessons accessed. Students who watched videos or read content without clicking the 'Complete Lesson' button show 0% completion.

Solution: Inform your students that they need to click 'Complete Lesson' (or the lesson completion button) in the Thinkific course player for completion tracking to work. This is a Thinkific platform behavior, not an API issue. For dashboards where lesson access matters more than explicit completion marking, use the updated_at field to infer recent activity instead of relying solely on percentage_completed.

### Orders query returns an empty items array despite existing orders

Cause: Date filter parameters (created_at[gte] and created_at[lte]) are not in the correct ISO 8601 format, or the DateRangePicker values are empty and the filter is excluding all records.

Solution: Verify that the date filter values from the DateRangePicker are formatted as ISO 8601 strings (YYYY-MM-DDTHH:mm:ssZ). If the DateRangePicker returns date strings in a different format, add a transformer in the parameter field to convert: new Date(dateRange.start).toISOString(). If the date range pickers are empty on initial load, add null-coalescing logic to omit the date parameters when no range is selected.

```
// Convert DateRangePicker values to ISO format for Thinkific
// In query params:
// created_at[gte]: {{ dateRange.start ? new Date(dateRange.start).toISOString() : '' }}
// created_at[lte]: {{ dateRange.end ? new Date(dateRange.end).toISOString() : '' }}
```

## Frequently asked questions

### Does Retool have a native Thinkific connector?

No. Retool does not have a dedicated native connector for Thinkific as of 2026. You connect via a generic REST API Resource using Thinkific's REST API with custom authentication headers. The setup requires adding X-Auth-API-Key (your API key) and X-Auth-Subdomain (your school subdomain) as global headers in the Resource configuration — this approach provides full access to all Thinkific API endpoints.

### What is the difference between the Thinkific subdomain and a custom domain?

Your Thinkific subdomain is the unique identifier for your school assigned at registration — it appears in your original Thinkific URL (yourschool.thinkific.com). Even if you use a custom domain (e.g., courses.yourcompany.com) for your school's public-facing URL, the original Thinkific subdomain is still required for API authentication. Use the Thinkific subdomain in the X-Auth-Subdomain header, not your custom domain.

### Can I create or modify enrollments from Retool?

Yes. Thinkific's API supports creating enrollments via POST /api/v1/enrollments with a JSON body containing user_id and course_id. You can build a Retool Form where admins enter a student email (look up the user ID first with GET /api/v1/users?search=email), then trigger the enrollment creation POST. This enables granting course access to students directly from Retool without logging into Thinkific's admin panel.

### How do I handle Thinkific schools with thousands of students?

Thinkific's API limits responses to 50 items per page. For large schools, implement pagination in Retool using the page URL parameter and bind it to a Table's pagination state. Alternatively, use a Retool Workflow on a nightly schedule to export all enrollments to your internal database and build the dashboard against that local copy — this approach handles very large datasets without hitting Thinkific API rate limits during dashboard load.

---

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