Connect Retool to ADP using a REST API Resource with OAuth 2.0 and client certificate authentication. Configure the base URL and credentials in the Resources tab to query the Workers, Pay, and Time APIs. The setup takes about 30 minutes due to ADP's multi-step auth requirements and gives HR and management teams a dashboard to view employee data without full ADP access.
| Fact | Value |
|---|---|
| Tool | ADP |
| Category | Other |
| Method | REST API Resource |
| Difficulty | Advanced |
| Time required | 30 minutes |
| Last updated | April 2026 |
Why Connect Retool to ADP?
ADP provides powerful HR and payroll capabilities, but access management is often a bottleneck: full ADP accounts are expensive and carry broad permissions, while managers and HR business partners frequently need read access to just their team's data — headcount, pay grades, time-off balances, and department cost summaries. A Retool app connected to ADP's API bridges this gap by exposing only the data each role needs, within the controlled access model of your Retool deployment.
ADP's API ecosystem covers three primary data domains: workforce (Workers API for employee records, org structure, and personal/contact data), payroll (Pay API for payroll run summaries, earnings, deductions, and YTD totals), and time (Time API for time cards, approvals, and time-off requests). Combining these in a Retool dashboard gives HR business partners a complete view of their population — who is on the team, what they earn at a summary level, and their time patterns — all within a single interface that can be filtered to their specific departments or cost centers.
The integration requires working through ADP's multi-step authentication setup (developer portal registration, app configuration, certificate generation, and credential approval), which is more involved than most REST API integrations. However, once configured, the Retool queries are straightforward REST calls that return consistently structured JSON, and the security model — mutual TLS plus OAuth — provides enterprise-grade protection appropriate for sensitive HR data. ADP also provides a sandbox environment that mirrors production data structure, allowing thorough testing before connecting to live payroll systems.
Integration method
Retool connects to ADP through a REST API Resource configured with ADP's OAuth 2.0 client credentials flow, which requires both a client ID/secret pair and a mutual TLS (mTLS) client certificate for all API requests. The base URL and authentication headers are configured once in the Resources tab. Retool proxies all requests server-side, keeping credentials off the browser. JavaScript transformers reshape ADP's deeply nested JSON responses into flat data structures for Retool's Table and Chart components.
Prerequisites
- A Retool account (Cloud or self-hosted) with permission to add Resources — self-hosted is preferred for ADP integrations to keep HR data within your network
- ADP API credentials: a registered application in the ADP Marketplace or ADP Developer Portal with a client ID and client secret
- An mTLS client certificate (X.509 certificate and private key) issued through ADP's developer portal or your organization's ADP contract
- Access to ADP's sandbox environment for testing before connecting to production payroll data
- Understanding of OAuth 2.0 client credentials flow and certificate-based authentication — this integration requires more setup than typical REST APIs
Step-by-step guide
Register an ADP API application and obtain credentials
Before configuring Retool, you must register an application through ADP's developer ecosystem. Navigate to developers.adp.com and sign in with your ADP account. If your organization has an ADP Marketplace agreement, you may register through your ADP client administrator. In the developer portal, create a new application. Specify: - Application name: 'Retool Internal Dashboard' or similar - APIs needed: Select the specific ADP API products relevant to your use case: HR Management API (Workers), Payroll API (Pay), or Time Management API - Redirect URIs: For server-to-server (client credentials) flows, the redirect URI is not required, but you may need to specify a placeholder Once the application is created, ADP provides: 1. A Client ID (application identifier) 2. A Client Secret (confidential credential) 3. Instructions for generating or uploading an mTLS client certificate For the client certificate, ADP requires mutual TLS — every API call must present a client certificate that ADP verifies against your registered application. Generate a self-signed certificate or obtain one from your organization's PKI. Upload the public certificate (PEM format) to your ADP application configuration. Keep the private key secure. Store all credentials in Retool Settings → Configuration Variables as secret variables: ADP_CLIENT_ID, ADP_CLIENT_SECRET. The client certificate and private key require special handling — for self-hosted Retool, you can configure mTLS at the infrastructure level. For Retool Cloud, implement the token exchange in a JavaScript query that uses the certificate via a Node.js crypto library approach.
Pro tip: ADP requires using a separate sandbox endpoint URL (api.adp.com for production, sandbox endpoints for testing). Test all queries against the ADP sandbox environment first — ADP sandbox data is realistic but synthetic, protecting you from accidentally modifying production payroll records during development.
Expected result: An ADP API application is registered in the developer portal with Client ID, Client Secret, and a client certificate. Credentials are saved as secret configuration variables in Retool. The mTLS certificate is configured for use with the ADP API endpoint.
Obtain an OAuth access token using client credentials flow
ADP's API requires an OAuth 2.0 Bearer token obtained via the client credentials grant type. The token request itself must also be made using the mTLS client certificate, making this a certificate-authenticated OAuth flow. Create a JavaScript query in your Retool app named getAdpToken. This query calls ADP's token endpoint. The ADP OAuth token URL for production is https://accounts.adp.com/auth/oauth/v2/token and for sandbox it is https://accounts.adpapis.com/auth/oauth/v2/token. The token request is a POST with: - Content-Type: application/x-www-form-urlencoded - Body: grant_type=client_credentials&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET} - The mTLS client certificate presented as part of the TLS handshake For Retool Cloud deployments where mTLS certificate configuration at the TLS layer is not possible, an alternative approach is to deploy a lightweight proxy service (a small Node.js or Python service in your infrastructure) that holds the client certificate and forwards authenticated requests. The Retool REST API Resource then points to this proxy rather than directly to ADP. For self-hosted Retool, configure the client certificate at the nginx or reverse proxy layer that fronts the Retool db_connector service. Set the certificate path in the db_connector environment configuration. Once configured, the token exchange and subsequent API calls are transparent — Retool presents the certificate automatically as part of each outbound HTTPS connection. Store the returned access_token in a Retool state variable. ADP tokens typically expire after 3600 seconds (1 hour). Run this query on page load and add an hourly refresh.
1// JavaScript query: exchange ADP client credentials for access token2// Note: For full mTLS, this requires certificate configuration at the infrastructure level3// For Retool Cloud, route through an mTLS-capable proxy service45const clientId = retoolContext.configVars.ADP_CLIENT_ID;6const clientSecret = retoolContext.configVars.ADP_CLIENT_SECRET;78// Token endpoint — use sandbox URL for testing9const tokenUrl = 'https://accounts.adp.com/auth/oauth/v2/token';1011const body = new URLSearchParams({12 grant_type: 'client_credentials',13 client_id: clientId,14 client_secret: clientSecret15}).toString();1617const response = await fetch(tokenUrl, {18 method: 'POST',19 headers: {20 'Content-Type': 'application/x-www-form-urlencoded'21 },22 body: body23 // mTLS certificate is configured at the infrastructure/proxy layer24});2526const tokenData = await response.json();2728if (tokenData.access_token) {29 await adpAccessToken.setValue(tokenData.access_token);30 return { success: true, expires_in: tokenData.expires_in };31} else {32 throw new Error('ADP token exchange failed: ' + JSON.stringify(tokenData));33}Pro tip: ADP access tokens expire after 1 hour. If your Retool app is used throughout the workday, add a Retool Workflow with an hourly schedule trigger that refreshes the token and stores it in a Retool Database table. App queries then read from the database table rather than the state variable, ensuring the token is always fresh regardless of when each user opens the app.
Expected result: The JavaScript query exchanges client credentials for an ADP access token and stores it in the adpAccessToken state variable. The token can be verified by decoding the JWT and checking its expiry timestamp.
Add an ADP REST API Resource and query Workers
Navigate to Resources tab → Add Resource → REST API. Configure the resource: - Name: ADP Workers API - Base URL: https://api.adp.com (production) or the ADP sandbox URL provided in your developer portal - Headers: Authorization: Bearer {{ adpAccessToken.value }} Click Save. Create a new query using this resource. Set the method to GET and the path to /hr/v2/workers. This is ADP's HR Management API endpoint for retrieving worker records. ADP's Workers endpoint supports several useful query parameters: - $top: {{ pagination.pageSize || 50 }} — number of records to return (ADP uses OData-style pagination) - $skip: {{ pagination.page * 50 || 0 }} — offset for pagination - $filter: add OData filter expressions for active workers: workers/workAssignments/assignmentStatus/statusCode/codeValue eq 'A' Set the query to Run on page load. Add a JavaScript transformer to flatten ADP's deeply nested response structure — ADP returns worker data with several layers of nesting (workers array → each worker → workAssignments array → businessCommunication → etc.). Drag a Table component onto the canvas. Bind it to {{ workersQuery.data }}. Configure columns for: associate OID (unique identifier), name, job title, department, location, hire date, and employment status. Add Search and filter components for department and location.
1// JavaScript transformer to flatten ADP Workers API response2// ADP returns deeply nested JSON — this flattens it for Table display3const workers = (data.workers || []);45return workers.map(worker => {6 const name = worker.person?.legalName || {};7 const assignment = (worker.workAssignments || [])[0] || {};8 const position = (assignment.homeOrganizationalUnits || [])[0] || {};9 const dept = (assignment.homeOrganizationalUnits || []).find(u => u.typeCode?.codeValue === 'Department') || {};10 const location = assignment.homeWorkLocation?.address?.cityName || '';1112 return {13 associate_oid: worker.associateOID,14 full_name: [name.givenName, name.familyName].filter(Boolean).join(' '),15 job_title: assignment.jobTitle || '',16 department: dept.nameCode?.longName || '',17 location: location,18 hire_date: assignment.hireDate || '',19 status: assignment.assignmentStatus?.statusCode?.codeValue || '',20 worker_id: assignment.workerID?.idValue || ''21 };22});Pro tip: ADP's Workers API uses OData query syntax for filtering. Common filters: workers/workAssignments/assignmentStatus/statusCode/codeValue eq 'A' (active employees only), or workers/workAssignments/homeOrganizationalUnits/nameCode/longName eq 'Engineering' (by department). Test filters in the ADP sandbox first to verify they return expected results.
Expected result: The Table displays employee records from ADP with names, job titles, departments, and locations. Pagination controls load additional pages of workers. Search and filter inputs narrow the displayed results.
Query payroll summary data from the Pay API
Extend your dashboard with payroll summary data. Create a second query using your ADP REST API Resource targeting the Pay API. ADP's Pay API endpoint for payroll run outputs is under the /payroll path. Set the method to GET and the path to /payroll/v1/payroll-output. Add query parameters for filtering by pay period. ADP's Pay API uses OData syntax for filtering: $filter=payrollAgreementID/idValue eq '{{ payGroupSelect.value }}'. Add a pay group Select component populated from a query to /payroll/v1/payroll-output (without filters) that returns available pay group IDs. The Pay API response includes earningsData, deductionsData, taxesData, and checkData arrays. Add a JavaScript transformer that aggregates these into department-level or cost-center-level summaries: Drag a second Table component onto a Payroll tab in your app. Bind it to the aggregated payroll data. Display columns: department/cost center, employee count, total gross pay, total deductions, total taxes, total net pay. Use Retool's Summary component (or a set of Stat components) to show organization-wide totals at the top. Add a DateRange or pay period Select component that filters the payroll query by pay period start/end dates. When the pay period changes, the query re-runs and the Table updates. For finance and HR leadership who need this data for budget reporting, add a download button that triggers a JavaScript query to format the table data as CSV and initiates a browser download using Retool's file download utility.
1// JavaScript transformer to aggregate ADP Pay API data by department2const outputs = data.payrollOutput || data['payroll-output'] || [];34// Aggregate by department cost center5const deptMap = {};67outputs.forEach(record => {8 const dept = record.workerDepartmentCode || 'Unknown';9 if (!deptMap[dept]) {10 deptMap[dept] = { department: dept, employee_count: 0, gross_pay: 0, deductions: 0, taxes: 0, net_pay: 0 };11 }12 deptMap[dept].employee_count++;13 deptMap[dept].gross_pay += parseFloat(record.totalGrossPayAmount?.amountValue || 0);14 deptMap[dept].deductions += parseFloat(record.totalDeductionAmount?.amountValue || 0);15 deptMap[dept].taxes += parseFloat(record.totalTaxAmount?.amountValue || 0);16 deptMap[dept].net_pay += parseFloat(record.totalNetPayAmount?.amountValue || 0);17});1819return Object.values(deptMap).map(d => ({20 ...d,21 gross_pay: d.gross_pay.toFixed(2),22 deductions: d.deductions.toFixed(2),23 taxes: d.taxes.toFixed(2),24 net_pay: d.net_pay.toFixed(2)25}));Pro tip: ADP Pay API data is highly sensitive. In Retool, use query-level access control to ensure that the payroll queries are only accessible to users in specific Retool groups (e.g., 'HR Leadership', 'Finance'). Regular managers should see headcount data but not detailed compensation figures.
Expected result: The Payroll tab displays department-level payroll summaries for the selected pay period, with aggregate gross pay, deductions, taxes, and net pay. Organization-wide totals appear in Summary components at the top.
Build a manager time card review panel
Add a Time Management section to your HR dashboard using ADP's Time API. This gives managers visibility into their direct reports' time cards without requiring full ADP access. Create a third query using the ADP REST API Resource. Set the method to GET and the path to /time/v1/workers/{workerID}/time-cards (or the equivalent ADP Time API endpoint available in your subscription). Pass the worker IDs of the manager's direct reports as individual requests, or use the team-level endpoint if available in your ADP subscription. Since each manager should see only their team's data, add a personalization step: create a JavaScript query on page load that fetches the current Retool user's ADP worker ID from an internal mapping table (a PostgreSQL table that maps Retool user emails to ADP worker IDs). Then use that worker ID to query the ADP Workers API for the manager's direct reports, and use those worker IDs to fetch time card data. Drag a Table component onto a Time Cards tab. Display: employee name, pay period, regular hours, overtime hours, time-off hours, and approval status. Add conditional row colors for unapproved overtime (red) and time cards pending review (yellow). Add an Approve button that sends a POST or PATCH request to ADP's time approval endpoint for the selected employee's time card. Include a confirmation modal that shows the employee name and total hours being approved. In the success handler, refresh the time cards query and show a notification. For complex HR workflows involving ADP data combined with internal HR systems, Retool Workflows, and multi-step approval chains, RapidDev's team can help architect and implement the complete solution.
1// JavaScript transformer for ADP time cards2const timeCards = Array.isArray(data) ? data : (data.timeCards || []);34return timeCards.map(card => {5 const totalRegular = parseFloat(card.regularHours?.quantity || 0);6 const totalOT = parseFloat(card.overtimeHours?.quantity || 0);7 const totalTO = parseFloat(card.timeOffHours?.quantity || 0);89 return {10 worker_id: card.worker?.workerID?.idValue || '',11 employee_name: card.worker?.person?.legalName?.formattedName || '',12 pay_period_start: card.payPeriod?.startDate || '',13 pay_period_end: card.payPeriod?.endDate || '',14 regular_hours: totalRegular.toFixed(2),15 overtime_hours: totalOT.toFixed(2),16 time_off_hours: totalTO.toFixed(2),17 approval_status: card.approvalStatusCode?.codeValue || 'Pending',18 has_unapproved_ot: totalOT > 0 && card.approvalStatusCode?.codeValue !== 'APPROVED'19 };20});Pro tip: ADP's Time API endpoint paths and response schema vary significantly between ADP products (Workforce Now, Vantage HCM, Run). Verify the exact endpoint URLs and response field names against your organization's specific ADP product documentation or API spec sheet, as the examples here are based on ADP Workforce Now conventions.
Expected result: The Time Cards tab shows time entries for the manager's direct reports with hours breakdowns and approval status. Unapproved overtime rows are highlighted. Clicking Approve sends the approval to ADP and refreshes the table.
Common use cases
Build an HR headcount and org chart dashboard
Create a Retool panel that displays all active employees from the ADP Workers API, filterable by department, location, job title, and employment status. HR business partners can view headcount by department, see hire dates and tenure, and drill down to individual employee records for basic contact and position information. The dashboard shows aggregate metrics (total headcount, new hires in last 30 days, departures in last 30 days) in Summary components at the top.
Build an employee directory dashboard that queries the ADP Workers API for active associates. Show employee name, job title, department, location, hire date, and manager name in a Table. Add filters for department and location. Display headcount totals by department in a bar chart above the table. Include a detail view that shows full employee contact info when a row is selected.
Copy this prompt to try it in Retool
Create a payroll summary and cost center report
Build a Retool reporting tool that queries ADP's Pay API for payroll run summaries by cost center or department. Finance and HR leaders can see total gross pay, deductions, net pay, and headcount for each cost center for a selected pay period. The dashboard shows period-over-period comparison using Chart components and lets users export the summary data. This replaces manual payroll report requests to the HR operations team.
Create a payroll cost dashboard that fetches ADP payroll run summaries for a selected pay period. Group the data by cost center and show total gross pay, benefits deductions, taxes, and net pay in a Table with subtotals. Add a line chart showing total payroll cost trend over the last 12 pay periods. Include filters for cost center and pay group.
Copy this prompt to try it in Retool
Build a manager time and attendance approval panel
Create a Retool tool that surfaces time card data from ADP's Time API for a manager's direct reports. Managers can review submitted time cards, check for missed punches or unapproved overtime, and see time-off request balances across their team. The panel shows a weekly summary for each direct report and flags hours that require approval or have exceptions, allowing managers to take action from Retool rather than navigating ADP's time management interface.
Build a time card review panel that queries ADP time entries for the current pay period for all employees under the logged-in manager's worker ID. Show employee name, total regular hours, overtime hours, time-off hours, and approval status in a Table. Flag rows with unapproved overtime in red. Add an Approve button that sends an approval action to the ADP Time API for selected rows.
Copy this prompt to try it in Retool
Troubleshooting
OAuth token request fails with 'invalid_client' or SSL handshake error
Cause: ADP's token endpoint requires mutual TLS authentication alongside the client credentials. If the client certificate is not being presented during the TLS handshake (because it is not configured at the infrastructure level), ADP's server rejects the connection before the OAuth exchange even begins.
Solution: For self-hosted Retool, configure the client certificate at the nginx reverse proxy or in the db_connector service environment using the NODE_EXTRA_CA_CERTS or equivalent certificate configuration. For Retool Cloud, deploy a lightweight mTLS proxy (Node.js with https.Agent configured with cert and key) in your infrastructure and point the Retool resource to the proxy URL rather than directly to ADP's API endpoint.
Workers API returns 404 Not Found for the /hr/v2/workers endpoint
Cause: The ADP API endpoint path depends on your organization's ADP product and subscription. ADP Workforce Now, ADP Vantage HCM, and ADP Run have different API paths and versions. Using the wrong path for your product results in a 404.
Solution: Check your ADP developer portal application configuration to see which API products are enabled and what their base endpoint paths are. The correct path for ADP Workforce Now may be /hr/v2/workers, while other products use different versioned paths. Test the endpoint in ADP's API Explorer tool (available in the developer portal sandbox) to confirm the correct path before configuring Retool.
Workers query returns data but all employee names are empty strings
Cause: ADP's Workers API returns names in a deeply nested structure: workers[].person.legalName.givenName and workers[].person.legalName.familyName. The JavaScript transformer may be accessing incorrect nested paths, or ADP may be returning a different name structure (e.g., preferredName instead of legalName) depending on your organization's configuration.
Solution: In the Retool query's debug output, click the response data and navigate the JSON tree to find where names are stored. Common paths include: person.legalName.givenName, person.legalName.familyName, or person.preferredName.formattedName. Update the transformer to use the path structure present in your organization's specific ADP response. Add a fallback: person.legalName?.formattedName || [name.givenName, name.familyName].join(' ') to handle both name formats.
1// Safe name extraction with fallbacks for ADP worker response2const legalName = worker.person?.legalName || {};3const fullName = legalName.formattedName 4 || [legalName.givenName, legalName.familyName].filter(Boolean).join(' ')5 || 'Unknown';Pay API returns 403 Forbidden even though the Workers API works with the same token
Cause: ADP uses separate API product scopes, and the OAuth token may only have the scope for the HR/Workers API but not for the Payroll API. Different ADP API products require explicit authorization on both the application registration and the token scope.
Solution: In the ADP developer portal, verify that the Payroll API product is added to your application configuration. Check the scopes listed on your application and ensure they include the payroll scope identifier (the exact scope name varies by ADP product — check the developer portal documentation). If the scope is missing, add it to your application and regenerate credentials. Then request a new token that includes the payroll scope.
Best practices
- Store all ADP credentials (Client ID, Client Secret) as secret configuration variables in Retool Settings — ADP credentials can be used to access sensitive payroll data and must never appear in query code or browser network requests.
- Use Retool's self-hosted deployment for ADP integrations wherever possible — HR and payroll data is subject to strict privacy regulations (GDPR, CCPA, HIPAA in some cases) and keeping data within your own VPC reduces compliance risk.
- Implement role-based access control in Retool using permission groups to restrict payroll data visibility — managers should see headcount and org data but not individual compensation details, which should be limited to HR and finance roles.
- Test all queries in ADP's sandbox environment before connecting to production — ADP sandbox data is synthetic but structurally identical to production, allowing full testing without risk of accessing or modifying real payroll records.
- Cache ADP Workers API responses aggressively (1-hour TTL) since employee data changes infrequently — this reduces API call volume, stays within ADP's rate limits, and improves dashboard load times for HR teams who open the app frequently.
- Handle ADP's OData pagination correctly — the Workers API may return a maximum of 100 records per request, and large organizations will require multiple paginated requests to retrieve the full workforce. Implement a JavaScript query that loops through pages until the response indicates no more records.
- Log all payroll data access in an internal audit table with the Retool user's email, the data accessed, and the timestamp — this creates a compliance audit trail for who viewed sensitive compensation data and when.
- Implement token refresh logic with a Retool Workflow on an hourly schedule — ADP tokens expire after 1 hour, and long-running Retool sessions that try to use an expired token will fail silently if token refresh is not handled.
Alternatives
Choose QuickBooks if your HR data need is primarily financial reporting and payroll expense tracking rather than workforce management, as QuickBooks has a simpler API authentication model.
Choose FreshBooks if you need a simpler API for tracking contractor time and invoicing rather than full enterprise payroll and HR data management.
Choose Harvest if your primary need is project-based time tracking and invoicing with a straightforward REST API, rather than enterprise payroll and HR data.
Frequently asked questions
Why does ADP require a client certificate in addition to OAuth credentials for API access?
ADP uses mutual TLS (mTLS) as an additional security layer beyond standard OAuth because its APIs expose highly sensitive payroll and HR data. In mTLS, both the server and the client present certificates, proving identity at the network layer before any application-level authentication occurs. This makes it significantly harder for unauthorized parties to impersonate legitimate API clients even if they obtain OAuth credentials.
Can Retool Cloud be used for ADP integrations or is self-hosted Retool required?
Retool Cloud can technically be used, but it requires additional steps to handle ADP's mTLS requirement. Since Retool Cloud does not support direct client certificate configuration for outbound API calls, you need to deploy an mTLS-capable proxy service in your infrastructure that holds the certificate and forwards authenticated requests to ADP. Retool then calls the proxy. Self-hosted Retool is simpler because the certificate can be configured at the infrastructure level. For ADP with sensitive payroll data, self-hosted is also the preferred choice for data residency compliance.
Which ADP APIs are available through the ADP Marketplace vs. the developer portal?
ADP's API ecosystem has two access paths. The ADP Marketplace is for certified ISVs (software vendors) building products that integrate with ADP as part of a commercial partnership. The ADP Developer Portal (developers.adp.com) is for organizations building internal integrations for their own use. For building a private Retool dashboard against your own organization's ADP account, you typically work through the developer portal. Access to specific APIs (Workers, Pay, Time) depends on which ADP products your organization has licensed.
How do I handle ADP's OData pagination to get all employees in a large organization?
ADP's HR API supports OData $top and $skip parameters for pagination. Create a JavaScript query that starts with $top=100&$skip=0, checks if the response returned a full page (100 records), then makes additional requests with incremented $skip values (100, 200, 300, etc.) until a partial page is returned — indicating you have fetched all records. Combine all results into a single array. For very large organizations (10,000+ employees), cache this full dataset in a Retool Database table populated by a nightly Workflow rather than fetching everything on each page load.
What is the difference between ADP Workforce Now and ADP Vantage HCM in terms of Retool API integration?
Both platforms use the same ADP API framework and authentication model (OAuth 2.0 with mTLS), but they have different API endpoint paths and response schemas. ADP Workforce Now is designed for mid-market businesses and has the more common API implementation. ADP Vantage HCM targets enterprise customers with additional capabilities. The API version paths, supported OData filter syntax, and response field names differ between products. Always reference your specific ADP product's API documentation from the developer portal rather than generic ADP API examples.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation