# How to Integrate Retool with Practo

- Tool: Retool
- Difficulty: Intermediate
- Time required: 25 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Practo by creating a REST API Resource with Practo's API base URL and authentication credentials. Use Practo's API to build clinic operations panels that manage appointments, patient schedules, and consultation queues — giving healthcare administrators a unified dashboard without navigating Practo's built-in interface for every operational task.

## Build a Practo Clinic Operations Dashboard in Retool

Practo is the dominant healthcare platform across India and Southeast Asia, used by clinics, hospitals, and individual practitioners to manage their patient-facing operations. While Practo's native interface works well for day-to-day scheduling, operations managers and clinic administrators often need a more flexible view — tracking appointment volumes across multiple practitioners, monitoring consultation queue length in real time, or combining Practo data with internal billing records. Retool provides exactly this capability through a direct API integration.

With a Retool-Practo integration, clinic administrators can view all appointments for a day or week in a sortable table, filter by practitioner or appointment type, monitor queue status for walk-in patients, and track consultation completion rates. When combined with an internal database in the same Retool app, you can join Practo appointment data with billing records, insurance claim statuses, or patient satisfaction scores for a complete operational picture.

Practo's API requires partner or enterprise access credentials — the exact authentication method depends on your Practo account type and API access tier. Retool's REST API Resource handles authentication header injection automatically, keeping your credentials server-side and never exposing them in the browser.

## Before you start

- A Practo partner or enterprise account with API access enabled (contact Practo's business team to request API credentials)
- Your Practo API key or OAuth client credentials (provided by Practo upon partner approval)
- A Retool account with permission to create Resources
- The Practo API base URL for your region (India: api.practo.com, or your assigned partner endpoint)
- Familiarity with Retool's query editor, Table component, and basic JavaScript transformers

## Step-by-step guide

### 1. Create a Practo REST API Resource in Retool

Navigate to the Resources tab in your Retool instance and click Add Resource. From the resource type list, select REST API. Name the resource 'Practo API' to distinguish it from other resources in your workspace.

In the Base URL field, enter your Practo API base URL. For most partners, this is https://api.practo.com — confirm the exact URL with your Practo account manager, as partner API endpoints may differ. Do not include a trailing slash.

For authentication, Practo typically uses API key authentication sent as a custom header. In the Headers section, add a new header with key = X-API-Key and value = your Practo API key. If your Practo integration uses Bearer token authentication instead, select Bearer Token from the Authentication dropdown and enter your token.

To keep credentials secure, store your API key as a Retool configuration variable first: go to Settings → Configuration Variables, create a variable named PRACTO_API_KEY, and mark it as Secret. Then in the header value field, use {{ retoolContext.configVars.PRACTO_API_KEY }} instead of the raw key value. This ensures the key is never exposed to frontend users.

If your Practo API requires additional headers such as X-Partner-Id or X-Clinic-Id, add those as default headers too. Click Save Changes when done.

**Expected result:** A Practo API REST Resource appears in your Resources list. Clicking Edit on the resource shows your configured base URL, authentication headers, and any custom headers.

### 2. Query appointments and patient schedules

Open your Retool app and create your first query. In the Code panel, click the + icon to add a new query. Name it getAppointments and select the Practo API resource.

Set Method to GET. In the Path field, enter /api/v1/appointments (adjust the path based on your Practo API version documentation). Add URL parameters to filter by date: key = date, value = {{ datePicker1.value }} to filter appointments by the selected date. Add another parameter: key = clinic_id, value = {{ dropdown_clinic.value }} if your account manages multiple clinic locations.

For pagination, add: key = page, value = {{ pagination.page || 1 }} and key = per_page, value = 50.

Create a second query named getPatientByPhone for patient lookup. Set Method to GET, Path to /api/v1/patients, and add URL parameters: key = phone, value = {{ textInput_phone.value }}.

Create a third query named getPractitioners (GET, /api/v1/practitioners) to populate a dropdown for filtering appointments by doctor. Run this query on page load to populate the filter controls.

Bind the getAppointments query result to a Table component by setting the table's Data property to {{ getAppointments.data.appointments }} (adjust the response path based on Practo's actual response structure).

```
// JavaScript transformer — flatten Practo appointment response for Table
const appointments = data.appointments || data.data || [];
return appointments.map(appt => ({
  id: appt.id,
  patient_name: appt.patient
    ? `${appt.patient.first_name || ''} ${appt.patient.last_name || ''}`.trim()
    : appt.patient_name || 'N/A',
  phone: appt.patient?.phone || appt.phone || 'N/A',
  practitioner: appt.doctor
    ? `Dr. ${appt.doctor.first_name} ${appt.doctor.last_name}`
    : appt.practitioner_name || 'N/A',
  appointment_time: appt.appointment_time
    ? new Date(appt.appointment_time).toLocaleTimeString('en-IN', {
        hour: '2-digit', minute: '2-digit'
      })
    : 'N/A',
  type: appt.consultation_type || appt.type || 'In-clinic',
  status: appt.status || 'scheduled',
  notes: appt.notes || ''
}));
```

**Expected result:** The getAppointments query populates the Table with today's appointments. The transformer flattens nested patient and practitioner objects into readable table columns with formatted time values.

### 3. Build appointment status update queries

Clinic staff need to update appointment statuses as patients progress through their visit — from scheduled, to checked-in, to in-consultation, to completed. Create a mutation query for this.

Create a new query named updateAppointmentStatus. Set Method to PATCH. In the Path field, enter /api/v1/appointments/{{ table_appointments.selectedRow.id }}. Set the Body type to JSON and enter the body:

{ "status": "{{ select_status.value }}", "updated_at": "{{ new Date().toISOString() }}" }

Add a Select component named select_status with options for your status values (e.g., 'scheduled', 'checked_in', 'in_consultation', 'completed', 'cancelled'). Add an Update Status button that triggers updateAppointmentStatus when clicked.

In the event handler for updateAppointmentStatus, set On Success to trigger getAppointments to refresh the appointment table, then show a notification 'Appointment status updated.' This creates the complete update-and-refresh loop.

For cancellations, create a separate cancelAppointment query (DELETE or PATCH with status=cancelled) and add a Cancel button with a confirmation modal. Use Retool's Modal component to display 'Are you sure you want to cancel this appointment?' before the query runs, preventing accidental cancellations.

For complex integrations with multiple clinics and practitioners, RapidDev's team can help architect a Retool solution that handles multi-location appointment management and integrates with additional data sources.

```
{
  "status": "{{ select_status.value }}",
  "notes": "{{ textInput_notes.value }}",
  "updated_by": "{{ retoolContext.currentUser.email }}",
  "updated_at": "{{ new Date().toISOString() }}"
}
```

**Expected result:** Selecting an appointment row in the table and clicking Update Status sends a PATCH request to Practo's API and refreshes the table to show the new status. The cancel button shows a confirmation modal before executing.

### 4. Create a practitioner availability and workload chart

Add a summary view showing each practitioner's appointment load for the day. This helps clinic managers identify overloaded doctors and redistribute patients to available slots.

Create a query named getAvailabilitySlots (GET, /api/v1/practitioners/{{ dropdown_practitioner.value }}/slots) with URL parameters date = {{ datePicker1.value }}, and duration = 15 (15-minute slot intervals). This returns the practitioner's available and booked time slots.

Create a JavaScript query named computeWorkloadSummary that aggregates appointment counts per practitioner. This query runs after getAppointments completes and groups the appointment data:

Bind the workload summary to a Chart component. Set the Chart type to Bar, x-axis to practitioner name, and y-axis to appointment count. This gives clinic managers an at-a-glance view of the day's distribution.

Add a date picker at the top of the app that controls all queries — when the date changes, getAppointments, getAvailabilitySlots, and computeWorkloadSummary all re-run with the new date. Configure this using the Run on value change setting in each query, or trigger them sequentially from the date picker's onChange event handler.

For the availability grid, add a Table component with practitioners as rows and time slots as columns. Use a transformer to build this matrix structure from the slots API response, marking booked slots as 'Booked' and available slots as 'Available'.

```
// JavaScript query — compute workload summary from appointment data
const appointments = getAppointments.data?.appointments || [];
const workloadMap = {};

appointments.forEach(appt => {
  const practitioner = appt.practitioner_name
    || (appt.doctor ? `Dr. ${appt.doctor.first_name} ${appt.doctor.last_name}` : 'Unknown');
  if (!workloadMap[practitioner]) {
    workloadMap[practitioner] = { name: practitioner, total: 0, completed: 0, pending: 0 };
  }
  workloadMap[practitioner].total++;
  if (appt.status === 'completed') workloadMap[practitioner].completed++;
  else workloadMap[practitioner].pending++;
});

return Object.values(workloadMap).sort((a, b) => b.total - a.total);
```

**Expected result:** The bar chart displays each practitioner's appointment count for the selected date. The availability grid shows booked vs. available slots. Changing the date picker refreshes all views simultaneously.

### 5. Connect Practo data with internal clinic records

The most valuable Retool-Practo integration joins appointment data from Practo with internal records — billing, insurance claims, patient satisfaction, or inventory. Add your clinic's internal database as a second resource in the same Retool app.

Create a PostgreSQL or MySQL resource (Resources tab → Add Resource → PostgreSQL/MySQL) pointing to your clinic's internal database. Name it 'Clinic DB'.

Create a database query named getPatientBilling:
SELECT patient_id, appointment_ref, invoice_amount, payment_status, insurance_claim_id, created_at FROM billing WHERE patient_phone = '{{ table_appointments.selectedRow.phone }}' ORDER BY created_at DESC LIMIT 10

When a clinic staff member selects an appointment in the Practo appointments table, this query automatically runs and populates a billing detail panel on the right side of the screen. This gives front desk staff instant visibility into whether a patient has outstanding balances before they complete their visit.

Add a second internal query named getPatientSatisfaction to pull NPS or satisfaction scores from your internal database for the selected patient. Display these alongside the Practo appointment history to give clinicians context about the patient's overall experience.

Create a JavaScript query named buildPatientProfile that merges the Practo patient record with internal data, producing a unified object that drives a summary panel at the top of the patient detail view.

```
SELECT
  b.patient_id,
  b.appointment_ref,
  b.invoice_amount,
  b.payment_status,
  b.insurance_claim_id,
  b.created_at,
  ic.claim_status,
  ic.approved_amount
FROM billing b
LEFT JOIN insurance_claims ic ON b.insurance_claim_id = ic.id
WHERE b.patient_phone = '{{ table_appointments.selectedRow.phone }}'
ORDER BY b.created_at DESC
LIMIT 10;
```

**Expected result:** Selecting an appointment from the Practo table loads billing and insurance data from the internal database in the detail panel on the right. The unified patient profile shows Practo appointment data alongside internal billing and satisfaction records.

## Best practices

- Store your Practo API key as a Secret configuration variable in Retool Settings → Configuration Variables — never hard-code it in query headers or body fields.
- Request separate read and write API keys from Practo if possible: use the read-only key for dashboards and reporting queries, and the write-enabled key only for mutation queries that update appointment status.
- Add JavaScript transformers to every Practo query to flatten nested response objects before binding data to Table components — Practo responses typically nest patient and practitioner data inside appointment objects.
- For clinics with multiple locations, always filter API queries by clinic_id and use a clinic selector dropdown at the top of your Retool app so staff see only relevant data.
- Use Retool's confirmation modal pattern before any status update or cancellation to prevent accidental changes to appointment records in a live clinical environment.
- Combine Practo appointment data with your internal billing database in the same Retool app to give front desk staff a complete patient picture without switching between systems.
- Log the Retool user's email ({{ retoolContext.currentUser.email }}) in every write operation body for audit trail purposes — critical in healthcare contexts with compliance requirements.
- Test all queries in Retool's staging environment (use a test clinic account) before connecting to your production Practo account with live patient data.

## Use cases

### Build a daily appointment queue dashboard

Create a Retool app that shows all appointments for a selected date across all practitioners, with columns for patient name, appointment time, practitioner, consultation type, and status. Add filters for practitioner and appointment type, plus a status update button that marks consultations as completed.

Prompt example:

```
Build a daily appointment queue panel with a date picker, a table showing all appointments from Practo's appointments endpoint filtered by date, status color-coding (scheduled=blue, in-progress=yellow, completed=green), and a button to update appointment status via a PATCH query.
```

### Practitioner schedule and availability manager

Build a scheduling management panel that shows each practitioner's availability slots for the next 7 days, highlights overbooking situations, and allows clinic staff to block out unavailable time slots. Include a summary chart showing appointment load distribution across the team.

Prompt example:

```
Create a practitioner availability dashboard that fetches schedule slots for all active practitioners, displays a grid view with each practitioner as a column and time slots as rows, highlights over-capacity slots in red, and includes a Chart component showing daily appointment counts per practitioner.
```

### Patient record and consultation history panel

Build a patient lookup panel where clinic staff can search by patient name or phone number, view their appointment history, see recent consultation notes, and check current prescription status. Include a summary of visit frequency and last consultation date.

Prompt example:

```
Build a patient management panel with a search input for patient name or phone number, a profile section showing patient demographics from Practo's patients endpoint, a timeline of past appointments, and a detail section showing consultation notes for the selected appointment.
```

## Troubleshooting

### All Practo API queries return 401 Unauthorized

Cause: The API key configured in the Retool resource is invalid, expired, or the header name doesn't match what Practo expects (e.g., using 'Authorization' instead of 'X-API-Key' or a partner-specific header name).

Solution: Check with your Practo account manager to confirm the correct authentication header name and verify your API key hasn't expired. In your Retool resource settings, confirm the header key matches exactly (case-sensitive). Test with a simple GET to a health-check endpoint like /api/v1/ping or /api/health to verify connectivity before building complex queries.

### Appointment queries return empty data even though appointments exist in Practo

Cause: The date format or clinic ID filter doesn't match what Practo's API expects. Practo's API may require dates in ISO 8601 format (YYYY-MM-DD) or a specific timezone-aware format.

Solution: Inspect the raw API response in Retool's query Response tab to see what Practo returns. Check the date URL parameter — if your date picker returns a JavaScript Date object, transform it using {{ moment(datePicker1.value).format('YYYY-MM-DD') }} to ensure the correct format. Also verify your clinic ID is correct by first querying the /api/v1/clinics endpoint to list all clinics your API key has access to.

```
// Format date for Practo API — use in URL parameter
// Key: date
// Value:
{{ new Date(datePicker1.value).toISOString().split('T')[0] }}
```

### Status update PATCH requests return 403 Forbidden

Cause: The API key being used for the Retool resource has read-only permissions and cannot perform write operations. Practo may issue separate API keys for read and write access.

Solution: Contact your Practo account manager to request a write-enabled API key or confirm which key has write permissions. Create a separate Retool resource named 'Practo API (Write)' with the write-enabled key, and point your mutation queries (updateAppointmentStatus, cancelAppointment) to this resource while keeping read queries on the read-only resource.

### Response data has deeply nested structure that doesn't bind to Retool Table columns

Cause: Practo's API returns nested objects (patient nested inside appointment, doctor nested inside appointment) that Retool's Table component can't automatically flatten for column display.

Solution: Add a JavaScript transformer to every Practo query that accesses nested fields. Navigate to the query editor → Advanced tab → Add Transformer, and write a map function that extracts and flattens all nested fields you need as top-level keys. The transformed data then binds cleanly to Table columns.

```
// Transformer to flatten nested Practo appointment object
return (data.appointments || []).map(a => ({
  id: a.id,
  patient_name: `${a.patient?.first_name || ''} ${a.patient?.last_name || ''}`.trim(),
  doctor_name: `Dr. ${a.doctor?.first_name || ''} ${a.doctor?.last_name || ''}`.trim(),
  time: a.appointment_time,
  status: a.status,
  type: a.consultation_type
}));
```

## Frequently asked questions

### Does Practo have a public API available to all users?

Practo's API is not publicly available to all accounts — it requires partner or enterprise access that must be requested through Practo's business team. Individual clinic owners should contact Practo at business@practo.com to apply for API credentials. The API is primarily aimed at health systems, clinic chains, and software partners building on top of Practo's platform.

### Can I build a patient-facing app using Practo's API in Retool?

Retool is designed for internal tools, not patient-facing applications. Any Retool app built on Practo data should be used by clinic staff, administrators, and operations managers — not directly by patients. For patient-facing features (appointment booking, teleconsultation), use Practo's native patient app or embed Practo's booking widget in your website.

### How do I handle patient data privacy and HIPAA/DPDP compliance in Retool?

For healthcare data, deploy Retool as a self-hosted instance within your own infrastructure so patient data never leaves your network. Configure Retool's audit log feature to track all queries and data access. Restrict access to the Practo-connected app using Retool's permission groups so only authorized clinic staff can view patient records. India's Digital Personal Data Protection (DPDP) Act requires specific data handling practices — consult with a compliance specialist before processing patient data through any third-party tool.

### What happens if Practo's API is down or returns errors?

Add error handling in Retool by checking the query's error state ({{ getAppointments.error }}) and displaying a user-friendly message component when the API is unavailable. For critical operational dashboards, consider caching the last successful response in a Retool Database table and displaying a 'Data as of [timestamp]' banner when using cached data. Set up a Retool Workflow to ping Practo's health endpoint and notify via Slack if the API becomes unavailable.

### Can Retool receive real-time appointment updates from Practo via webhooks?

Yes, if Practo's API supports webhook notifications for appointment events (new booking, cancellation, status change), you can receive them in Retool Workflows. Create a Retool Workflow with a webhook trigger to get a unique endpoint URL, then register that URL in Practo's webhook settings. The workflow processes incoming appointment events and can update a Retool Database, trigger Slack notifications, or execute other actions in response.

---

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