# How to Integrate Retool with ScheduleOnce (OnceHub)

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

## TL;DR

Connect Retool to ScheduleOnce (now OnceHub) by creating a REST API Resource with OnceHub's base URL and API key authentication. Use OnceHub's REST API to build scheduling management dashboards that track bookings, monitor conversion rates across scheduling pages, and manage routing rules — giving operations teams direct access to scheduling data without logging into multiple tools.

## Build a ScheduleOnce Booking Management Dashboard in Retool

OnceHub (formerly ScheduleOnce) is a powerful scheduling platform used by sales, customer success, and operations teams to route inbound meeting requests and manage appointment calendars. While OnceHub's built-in reporting provides basic analytics, teams often need a more flexible view — filtering bookings by sales rep, comparing conversion rates across scheduling pages, or combining booking data with CRM records from Salesforce or HubSpot.

Retool bridges this gap by giving you direct query access to OnceHub's REST API in a configurable internal tool. Your ops team can view all pending and completed bookings, filter by date range, booking page, or assignee, and take actions like canceling or rescheduling — all from a single Retool panel. When combined with your CRM data, you can see whether booked meetings converted to opportunities, tracking the full funnel from scheduling link click to closed deal.

OnceHub's API uses simple API key authentication passed as a header. Retool's server-side proxy keeps this key secure and eliminates CORS concerns. The core scheduling operations — listing bookings, retrieving scheduling pages, managing team members, and tracking availability — are all accessible through the OnceHub REST API.

## Before you start

- An OnceHub account with at least one scheduling page configured
- An OnceHub API key (Account Settings → API → Generate API Key)
- A Retool account with permission to create Resources
- At least one active booking page or team member routing rule in OnceHub
- Familiarity with Retool's query editor and Table component basics

## Step-by-step guide

### 1. Create an OnceHub REST API Resource

Navigate to the Resources tab in your Retool instance and click Add Resource. Scroll through the resource types and select REST API. Name the resource 'OnceHub API' to keep it identifiable if you have multiple scheduling integrations.

In the Base URL field, enter https://api.oncehub.com. This is the base URL for OnceHub's REST API — all endpoint paths will be appended to this URL. Ensure there is no trailing slash after 'oncehub.com'.

OnceHub uses API key authentication passed as a request header. In the Headers section of the resource configuration, click Add Header. Set the header name to API-Key and the value to your OnceHub API key. You can find or generate your API key in OnceHub by going to your Account Settings, selecting the API section, and clicking Generate API Key.

For better security, store your API key as a configuration variable instead of pasting it directly. Go to Settings → Configuration Variables in Retool, create a new variable named ONCEHUB_API_KEY, mark it as Secret, and paste your key there. Then in the Header value field, use {{ retoolContext.configVars.ONCEHUB_API_KEY }} instead of the raw key.

Leave other settings at their defaults and click Save Changes. Retool will save the resource and make it available for queries in all apps in your workspace.

**Expected result:** An OnceHub API REST resource appears in your Resources list with API-Key header authentication configured and saved.

### 2. Query bookings and scheduling data

Create your first query to retrieve bookings from OnceHub. In your Retool app, open the Code panel and click the + icon to add a new query. Name it getBookings and select the OnceHub API resource you just created.

Set the Method to GET. In the Path field, enter /v2/bookings. OnceHub's bookings endpoint supports several query parameters for filtering. In the URL Parameters section, add the following parameters to control the results:
- starting_after: enter a date string like {{ dateRangePicker.startDate }} to filter bookings starting after a specific date
- ending_before: enter {{ dateRangePicker.endDate }} to set the end of the date range
- status: enter 'BOOKED' to retrieve only confirmed bookings (other options: 'CANCELED', 'COMPLETED', 'NO_SHOW')
- limit: enter 50 to control page size

For your Retool app layout, add a DateRangePicker component named dateRangePicker to control the date filter, and a Table component named table_bookings with its data bound to {{ getBookings.data.data }}.

To retrieve individual booking details when a row is selected, create a second query named getBookingDetail:
- Method: GET
- Path: /v2/bookings/{{ table_bookings.selectedRow.id }}

This detail query populates a side panel with the full booking record including custom form responses.

```
// JavaScript transformer — format booking list for display
const bookings = (data.data || []);
return bookings.map(booking => {
  return {
    id: booking.id,
    subject: booking.subject || 'Meeting',
    status: booking.status || 'UNKNOWN',
    start_time: booking.starting_at
      ? new Date(booking.starting_at).toLocaleString('en-US', {
          month: 'short', day: 'numeric',
          hour: '2-digit', minute: '2-digit'
        })
      : 'N/A',
    duration_min: booking.duration ? `${booking.duration} min` : 'N/A',
    attendee_name: booking.customer?.name || 'Unknown',
    attendee_email: booking.customer?.email || 'N/A',
    page_name: booking.booking_page?.name || 'N/A',
    assigned_to: booking.owner?.name || 'Unassigned'
  };
});
```

**Expected result:** The getBookings query returns a list of bookings filtered by the selected date range. The JavaScript transformer reshapes the response into clean table rows showing meeting details, attendee info, and assignment.

### 3. Retrieve scheduling pages and team members

Create queries to list scheduling pages and team members, which are needed to build dropdown filters and routing management panels in your Retool app.

Create a query named getSchedulingPages:
- Method: GET
- Path: /v2/booking-pages
- No additional parameters required for a basic list

This returns all scheduling pages in your OnceHub account. Each page object includes an id, name, url (the public booking link), and status. Bind these results to a Select or Dropdown component named dropdown_page so users can filter bookings by specific scheduling page.

Create a second query named getTeamMembers:
- Method: GET
- Path: /v2/users

This returns all users (team members) in your OnceHub account. Use this to populate an assignee filter dropdown, enabling managers to view bookings for a specific sales rep or customer success manager.

Combine these filters in your getBookings query by adding additional URL parameters:
- booking_page_id: {{ dropdown_page.value }} to filter by scheduling page
- owner_id: {{ dropdown_owner.value }} to filter by assigned team member

Set both dropdown components to have an 'All' option (empty string value) so users can clear the filter and see all bookings. Connect each dropdown's onChange event to trigger the getBookings query so the table refreshes immediately when filters change.

```
// JavaScript transformer — format scheduling pages for dropdown options
const pages = (data.data || []);
return [
  { label: 'All Scheduling Pages', value: '' },
  ...pages
    .filter(page => page.status === 'ACTIVE')
    .map(page => ({
      label: page.name || 'Unnamed Page',
      value: page.id,
      url: page.url || ''
    }))
    .sort((a, b) => a.label.localeCompare(b.label))
];
```

**Expected result:** The dropdown_page component populates with all active scheduling pages, and dropdown_owner populates with all team members. The bookings table filters correctly when either dropdown selection changes.

### 4. Build booking conversion analytics

Create a query to calculate booking conversion metrics across your scheduling pages. While OnceHub's API focuses on bookings data (confirmed appointments), you can compute conversion rate by comparing booked meetings to canceled or no-show meetings over the same period.

Create a query named getBookingsByStatus that fetches bookings grouped by status. Run separate GET requests to /v2/bookings with status=BOOKED, status=CANCELED, and status=NO_SHOW for the selected date range, then use a JavaScript query to combine the counts per scheduling page.

Create a JavaScript query named calcConversionMetrics:

This query reads results from three separate status queries and builds per-page summary statistics. Add a Chart component to your Retool app and bind its data to {{ calcConversionMetrics.data }}. Set the chart type to Bar, x-axis to page_name, and y-axis to booking_count.

For the conversion rate table, add a Table component with columns for page_name, total_scheduled, completed, canceled, no_show, and completion_rate. Apply conditional row colors using Retool's Table column formatting — red for pages with completion rates below 70%, green for pages above 90%.

Add a Summary Stats row above the table showing totals: total bookings this period, overall completion rate, and most active scheduling page. Bind these to {{ calcConversionMetrics.data }} aggregates using Text components.

```
// JavaScript query — calculate conversion metrics per scheduling page
// Assumes getBookedMeetings, getCanceledMeetings, getNoShowMeetings all ran first
const booked = (getBookedMeetings.data?.data || []);
const canceled = (getCanceledMeetings.data?.data || []);
const noShow = (getNoShowMeetings.data?.data || []);

// Group by scheduling page name
const pageMap = {};

const countByPage = (meetings, field) => {
  meetings.forEach(m => {
    const pageName = m.booking_page?.name || 'Unknown Page';
    if (!pageMap[pageName]) {
      pageMap[pageName] = { page_name: pageName, booked: 0, canceled: 0, no_show: 0 };
    }
    pageMap[pageName][field]++;
  });
};

countByPage(booked, 'booked');
countByPage(canceled, 'canceled');
countByPage(noShow, 'no_show');

return Object.values(pageMap).map(page => {
  const total = page.booked + page.canceled + page.no_show;
  return {
    ...page,
    total,
    completion_rate: total > 0
      ? `${((page.booked / total) * 100).toFixed(1)}%`
      : 'N/A'
  };
}).sort((a, b) => b.total - a.total);
```

**Expected result:** The metrics table shows all active scheduling pages with their booked, canceled, and no-show counts, plus calculated completion rates. The bar chart visually compares performance across scheduling pages.

### 5. Add booking actions and workflow integration

Add action capabilities to your Retool booking panel so operations teams can take direct actions on bookings without leaving the tool. OnceHub's API supports canceling bookings programmatically, which is the most commonly needed action.

Create a query named cancelBooking:
- Method: POST
- Path: /v2/bookings/{{ table_bookings.selectedRow.id }}/cancellation
- Body (JSON): { "cancellation_reason": "{{ textInput_cancelReason.value }}" }

In your Retool app, add a Button component labeled 'Cancel Booking' next to your bookings table. Set its onClick event handler to open a Confirmation Modal first (using a Modal component), then trigger the cancelBooking query on confirmation. After successful cancellation, trigger getBookings to refresh the table and show a success notification using Retool's Notification event handler.

For viewing the public booking page link of the selected booking, add a Text component that displays the scheduling page URL from the selected row: {{ getSchedulingPages.data.data.find(p => p.id === table_bookings.selectedRow.booking_page?.id)?.url || 'N/A' }}. Add a Button labeled 'Open Booking Page' that opens this URL in a new tab via the Open URL event handler action.

For complex scheduling management scenarios involving multiple routing rules, team calendars, and CRM integration, RapidDev's team can help architect a comprehensive Retool scheduling operations center that connects OnceHub bookings with your CRM and customer database.

```
// Query configuration for cancelBooking
// Method: POST
// Path: /v2/bookings/{{ table_bookings.selectedRow.id }}/cancellation
{
  "cancellation_reason": "{{ textInput_cancelReason.value || 'Canceled by operations team' }}",
  "notify_customer": true
}
```

**Expected result:** The Cancel Booking button opens a confirmation modal with a reason input. Confirming triggers the cancellation API call, sends the cancellation email to the attendee, and refreshes the bookings table to show the updated status.

## Best practices

- Store your OnceHub API key as a Secret configuration variable in Retool's Settings → Configuration Variables rather than pasting it directly into resource headers.
- Set the getSchedulingPages and getTeamMembers queries to run on page load so filter dropdowns are always populated when users open the dashboard.
- Add a confirmation modal before any destructive actions like booking cancellations — OnceHub automatically emails attendees when bookings are canceled via the API.
- Use Retool Workflows on a nightly schedule to cache booking conversion metrics in Retool Database, reducing the number of API calls your live dashboard makes during business hours.
- Combine OnceHub booking data with your CRM resource in the same Retool app to create a sales scheduling view that shows which booked meetings converted to pipeline opportunities.
- Apply conditional row formatting in your bookings Table — highlight overdue bookings (past start time with status still BOOKED) in yellow so operations teams can quickly identify issues.
- When filtering bookings by date range, always format date values as ISO 8601 strings using {{ new Date(dateRangePicker.value).toISOString() }} to avoid API format errors.

## Use cases

### Build a booking management and cancellation panel

Create a Retool app where operations teams can view all upcoming bookings across all scheduling pages, filter by date range and status, and take actions like canceling or rescheduling individual meetings. Add a detail panel that shows the full booking record including attendee information, custom form field answers, and calendar event links.

Prompt example:

```
Build a booking management dashboard with a date range picker, a Table showing all bookings with columns for name, email, meeting type, assigned rep, and status, plus Cancel and Reschedule action buttons that call the OnceHub API to update each booking.
```

### Scheduling page conversion rate tracker

Build a Retool dashboard that fetches all scheduling pages and calculates conversion metrics — visits, bookings, and booking rate — for each page over a selected time period. Add a Chart component to visualize which scheduling pages perform best and identify pages with low conversion that need attention.

Prompt example:

```
Create a scheduling analytics panel that lists all scheduling pages with their booking counts and conversion rates for the selected month, displays a bar chart comparing performance across pages, and highlights pages where the booking rate has dropped more than 20% from the previous period.
```

### Team scheduling load balancer view

Build an operational dashboard that shows the distribution of booked meetings across your sales or customer success team. Display each team member's upcoming meeting count, availability status, and booking load for the current week, helping managers identify when specific reps are overbooked and rebalance routing rules.

Prompt example:

```
Build a team scheduling panel that queries all team members from OnceHub, shows each person's meeting count for the current week sorted by load, and displays a color-coded capacity indicator so managers can quickly see who is at capacity and adjust routing rules accordingly.
```

## Troubleshooting

### API returns 401 Unauthorized on all queries

Cause: The API-Key header is missing, incorrectly named, or contains an expired or revoked OnceHub API key.

Solution: Verify the header name is exactly 'API-Key' (case-sensitive). Go to OnceHub Account Settings → API to confirm your key is active and not revoked. If using a configuration variable, check that the variable name matches exactly in your resource header value. Try pasting the key directly to test, then move back to a config variable once working.

### Bookings query returns an empty data array even though bookings exist

Cause: The date range filter parameters may be formatted incorrectly or outside the range where bookings exist. OnceHub expects ISO 8601 date format for the starting_after and ending_before parameters.

Solution: Check that your date parameters are formatted as ISO 8601 strings (e.g., 2026-01-01T00:00:00Z). If using a DateRangePicker component, format the value as: {{ new Date(dateRangePicker.startDate).toISOString() }}. Remove date filters entirely to confirm the API returns data before adding filter parameters back one at a time.

```
// Format date for OnceHub API URL parameter
// Key: starting_after
// Value:
{{ new Date(dateRangePicker.startDate).toISOString() }}
```

### Cancellation query fails with 400 Bad Request

Cause: The booking you are trying to cancel is already in a final state (CANCELED, COMPLETED, or NO_SHOW), or the request body is missing required fields.

Solution: Check the status of the selected booking before attempting cancellation. Add a conditional check in your Retool app: only show the Cancel button when {{ table_bookings.selectedRow.status === 'BOOKED' }}. If the body is malformed, verify the JSON structure matches OnceHub's API documentation and that the cancellation_reason field is present.

### Scheduling pages dropdown is empty despite active pages in OnceHub

Cause: The /v2/booking-pages endpoint may require additional parameters, or the API key does not have permissions to read booking page configurations.

Solution: Verify your OnceHub API key has full account access by testing the /v2/booking-pages endpoint directly in Retool's query preview. Check that pages are in ACTIVE status by temporarily removing any status filters in your query. If pages are returned in a nested structure, adjust your transformer to access the correct data path.

## Frequently asked questions

### Does OnceHub/ScheduleOnce have a native connector in Retool?

No, OnceHub does not have a native connector in Retool. You connect it as a REST API Resource using your OnceHub API key as a header. This requires knowing the endpoint paths, but all core operations — bookings, scheduling pages, and team management — are accessible through the OnceHub v2 REST API documented at developer.oncehub.com.

### Can I create new scheduling pages or booking rules from Retool?

OnceHub's API primarily supports reading and managing existing bookings rather than creating new scheduling page configurations. You can cancel bookings and retrieve booking details via the API. For creating or editing scheduling pages and routing rules, use the OnceHub web interface directly. Check the latest OnceHub API documentation for any newly added write endpoints.

### How do I combine OnceHub data with my CRM data in Retool?

Add your CRM as a second Resource in the same Retool app — for example, a Salesforce native connector or a HubSpot REST API resource. When a booking is selected in the table, use the attendee email from the OnceHub booking to trigger a CRM lookup query. Display both the scheduling data and CRM opportunity data side by side in a detail panel. This gives your sales team a complete view without switching between tools.

### What happens when I cancel a booking via the Retool API call?

When you cancel a booking using the OnceHub API from Retool, OnceHub automatically sends a cancellation notification email to the attendee using the email template configured in your OnceHub account. The booking status changes to CANCELED and the calendar event is removed from both the host and attendee's connected calendars. Always use a confirmation modal in Retool before triggering this action to prevent accidental cancellations.

### Can I use Retool Workflows to automate booking follow-ups with OnceHub?

Yes. You can create a Retool Workflow with a Schedule trigger that runs after business hours, queries OnceHub for that day's completed bookings, and triggers follow-up actions like inserting records into your CRM or sending Slack notifications to account owners. Combine the OnceHub API resource query with a Slack or database resource query in the same Workflow to automate post-meeting operations without manual intervention.

---

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