From 955fb67d514ecb24e85fef99f9d166f6d356d5f5 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 25 Mar 2026 10:42:24 -0700 Subject: [PATCH 1/6] feat(rippling): add Rippling HR integration with 19 tools --- apps/docs/components/icons.tsx | 11 + apps/docs/components/ui/icon-mapping.ts | 2 + apps/docs/content/docs/en/tools/meta.json | 1 + apps/docs/content/docs/en/tools/quiver.mdx | 5 +- apps/docs/content/docs/en/tools/rippling.mdx | 506 +++++++++ .../integrations/data/icon-mapping.ts | 16 +- .../integrations/data/integrations.json | 999 +++++++++++++++--- apps/sim/blocks/blocks/rippling.ts | 406 +++++++ apps/sim/blocks/registry.ts | 2 + apps/sim/components/icons.tsx | 11 + apps/sim/tools/registry.ts | 40 + apps/sim/tools/rippling/create_group.ts | 91 ++ apps/sim/tools/rippling/get_company.ts | 75 ++ .../tools/rippling/get_company_activity.ts | 125 +++ apps/sim/tools/rippling/get_current_user.ts | 57 + apps/sim/tools/rippling/get_employee.ts | 79 ++ apps/sim/tools/rippling/get_leave_balance.ts | 77 ++ apps/sim/tools/rippling/index.ts | 20 + apps/sim/tools/rippling/list_custom_fields.ts | 96 ++ apps/sim/tools/rippling/list_departments.ts | 94 ++ apps/sim/tools/rippling/list_employees.ts | 112 ++ .../list_employees_with_terminated.ts | 113 ++ .../sim/tools/rippling/list_leave_balances.ts | 107 ++ .../sim/tools/rippling/list_leave_requests.ts | 111 ++ apps/sim/tools/rippling/list_leave_types.ts | 87 ++ apps/sim/tools/rippling/list_levels.ts | 91 ++ apps/sim/tools/rippling/list_teams.ts | 89 ++ .../sim/tools/rippling/list_work_locations.ts | 102 ++ .../tools/rippling/process_leave_request.ts | 74 ++ apps/sim/tools/rippling/push_candidate.ts | 124 +++ apps/sim/tools/rippling/types.ts | 362 +++++++ apps/sim/tools/rippling/update_group.ts | 110 ++ 32 files changed, 4016 insertions(+), 179 deletions(-) create mode 100644 apps/docs/content/docs/en/tools/rippling.mdx create mode 100644 apps/sim/blocks/blocks/rippling.ts create mode 100644 apps/sim/tools/rippling/create_group.ts create mode 100644 apps/sim/tools/rippling/get_company.ts create mode 100644 apps/sim/tools/rippling/get_company_activity.ts create mode 100644 apps/sim/tools/rippling/get_current_user.ts create mode 100644 apps/sim/tools/rippling/get_employee.ts create mode 100644 apps/sim/tools/rippling/get_leave_balance.ts create mode 100644 apps/sim/tools/rippling/index.ts create mode 100644 apps/sim/tools/rippling/list_custom_fields.ts create mode 100644 apps/sim/tools/rippling/list_departments.ts create mode 100644 apps/sim/tools/rippling/list_employees.ts create mode 100644 apps/sim/tools/rippling/list_employees_with_terminated.ts create mode 100644 apps/sim/tools/rippling/list_leave_balances.ts create mode 100644 apps/sim/tools/rippling/list_leave_requests.ts create mode 100644 apps/sim/tools/rippling/list_leave_types.ts create mode 100644 apps/sim/tools/rippling/list_levels.ts create mode 100644 apps/sim/tools/rippling/list_teams.ts create mode 100644 apps/sim/tools/rippling/list_work_locations.ts create mode 100644 apps/sim/tools/rippling/process_leave_request.ts create mode 100644 apps/sim/tools/rippling/push_candidate.ts create mode 100644 apps/sim/tools/rippling/types.ts create mode 100644 apps/sim/tools/rippling/update_group.ts diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index a7ee06c5e8..0cf5773ca4 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -6270,6 +6270,17 @@ export function RedisIcon(props: SVGProps) { ) } +export function RipplingIcon(props: SVGProps) { + return ( + + + + ) +} + export function HexIcon(props: SVGProps) { return ( diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index 53ae7c0037..900229eaad 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -133,6 +133,7 @@ import { ReductoIcon, ResendIcon, RevenueCatIcon, + RipplingIcon, S3Icon, SalesforceIcon, SearchIcon, @@ -306,6 +307,7 @@ export const blockTypeToIconMap: Record = { reducto_v2: ReductoIcon, resend: ResendIcon, revenuecat: RevenueCatIcon, + rippling: RipplingIcon, s3: S3Icon, salesforce: SalesforceIcon, search: SearchIcon, diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index a29c07b06d..9ff8f3ff78 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -128,6 +128,7 @@ "reducto", "resend", "revenuecat", + "rippling", "s3", "salesforce", "search", diff --git a/apps/docs/content/docs/en/tools/quiver.mdx b/apps/docs/content/docs/en/tools/quiver.mdx index 2a5df8d1ca..14fbe522fd 100644 --- a/apps/docs/content/docs/en/tools/quiver.mdx +++ b/apps/docs/content/docs/en/tools/quiver.mdx @@ -59,8 +59,9 @@ Generate SVG images from text prompts using QuiverAI | --------- | ---- | ----------- | | `success` | boolean | Whether the SVG generation succeeded | | `output` | object | Generated SVG output | -| ↳ `file` | file | Generated SVG file | -| ↳ `svgContent` | string | Raw SVG markup content | +| ↳ `file` | file | First generated SVG file | +| ↳ `files` | json | All generated SVG files \(when n > 1\) | +| ↳ `svgContent` | string | Raw SVG markup content of the first result | | ↳ `id` | string | Generation request ID | | ↳ `usage` | json | Token usage statistics | | ↳ `totalTokens` | number | Total tokens used | diff --git a/apps/docs/content/docs/en/tools/rippling.mdx b/apps/docs/content/docs/en/tools/rippling.mdx new file mode 100644 index 0000000000..6eecade9a0 --- /dev/null +++ b/apps/docs/content/docs/en/tools/rippling.mdx @@ -0,0 +1,506 @@ +--- +title: Rippling +description: Manage employees, leave, departments, and company data in Rippling +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Rippling](https://www.rippling.com/) is a unified workforce management platform that brings together HR, IT, and Finance into a single system. Rippling lets companies manage payroll, benefits, devices, apps, and more — all from one place — while automating the tedious manual work that typically bogs down HR teams. Its robust API provides programmatic access to employee data, organizational structure, leave management, and onboarding workflows. + +**Why Rippling?** +- **Unified Employee System of Record:** A single source of truth for employee profiles, departments, teams, levels, and work locations — no more syncing data across disconnected tools. +- **Leave Management:** Full visibility into leave requests, balances, and types with the ability to approve or decline requests programmatically. +- **Company Insights:** Access company activity events, custom fields, and organizational hierarchy to power reporting and compliance workflows. +- **Onboarding Automation:** Push candidates directly into Rippling's onboarding flow, eliminating manual data entry when bringing on new hires. +- **Group Management:** Create and update groups for third-party app provisioning via SCIM-compatible endpoints. + +**Using Rippling in Sim** + +Sim's Rippling integration connects your agentic workflows directly to your Rippling account using an API key. With 19 operations spanning employees, departments, teams, leave, groups, and candidates, you can build powerful HR automations without writing backend code. + +**Key benefits of using Rippling in Sim:** +- **Employee directory automation:** List, search, and retrieve employee details — including terminated employees — to power onboarding checklists, offboarding workflows, and org chart updates. +- **Leave workflow automation:** Monitor leave requests, check balances, and programmatically approve or decline requests based on custom business rules. +- **Organizational intelligence:** Query departments, teams, levels, work locations, and custom fields to build dynamic org reports or trigger actions based on structural changes. +- **Candidate onboarding:** Push candidates from your ATS or recruiting pipeline directly into Rippling's onboarding flow, complete with job title, department, and start date. +- **Activity monitoring:** Track company activity events to build audit trails, compliance dashboards, or alert workflows when key changes occur. + +Whether you're automating new hire onboarding, building leave approval workflows, or syncing employee data across your tool stack, Rippling in Sim gives you direct, secure access to your HR platform — no middleware required. Simply configure your API key, select the operation you need, and let Sim handle the rest. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate Rippling into your workflow. Manage employees, departments, teams, leave requests, work locations, groups, candidates, and company information. + + + +## Tools + +### `rippling_list_employees` + +List all employees in Rippling with optional pagination + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of employees to return \(default 100, max 100\) | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `employees` | array | List of employees | +| ↳ `id` | string | Employee ID | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `workEmail` | string | Work email address | +| ↳ `personalEmail` | string | Personal email address | +| ↳ `roleState` | string | Employment status | +| ↳ `department` | string | Department name or ID | +| ↳ `title` | string | Job title | +| ↳ `startDate` | string | Employment start date | +| ↳ `endDate` | string | Employment end date | +| ↳ `manager` | string | Manager ID or name | +| ↳ `phone` | string | Phone number | +| `totalCount` | number | Total number of employees returned | + +### `rippling_get_employee` + +Get details for a specific employee by ID + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `employeeId` | string | Yes | The ID of the employee to retrieve | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Employee ID | +| `firstName` | string | First name | +| `lastName` | string | Last name | +| `workEmail` | string | Work email address | +| `personalEmail` | string | Personal email address | +| `roleState` | string | Employment status | +| `department` | string | Department name or ID | +| `title` | string | Job title | +| `startDate` | string | Employment start date | +| `endDate` | string | Employment end date | +| `manager` | string | Manager ID or name | +| `phone` | string | Phone number | + +### `rippling_list_employees_with_terminated` + +List all employees in Rippling including terminated employees with optional pagination + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of employees to return \(default 100, max 100\) | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `employees` | array | List of employees including terminated | +| ↳ `id` | string | Employee ID | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `workEmail` | string | Work email address | +| ↳ `personalEmail` | string | Personal email address | +| ↳ `roleState` | string | Employment status | +| ↳ `department` | string | Department name or ID | +| ↳ `title` | string | Job title | +| ↳ `startDate` | string | Employment start date | +| ↳ `endDate` | string | Employment end date | +| ↳ `manager` | string | Manager ID or name | +| ↳ `phone` | string | Phone number | +| `totalCount` | number | Total number of employees returned | + +### `rippling_list_departments` + +List all departments in the Rippling organization + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of departments to return | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `departments` | array | List of departments | +| ↳ `id` | string | Department ID | +| ↳ `name` | string | Department name | +| ↳ `parent` | string | Parent department ID | +| `totalCount` | number | Total number of departments returned | + +### `rippling_list_teams` + +List all teams in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of teams to return | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `teams` | array | List of teams | +| ↳ `id` | string | Team ID | +| ↳ `name` | string | Team name | +| ↳ `parent` | string | Parent team ID | +| `totalCount` | number | Total number of teams returned | + +### `rippling_list_levels` + +List all position levels in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of levels to return | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `levels` | array | List of position levels | +| ↳ `id` | string | Level ID | +| ↳ `name` | string | Level name | +| ↳ `parent` | string | Parent level ID | +| `totalCount` | number | Total number of levels returned | + +### `rippling_list_work_locations` + +List all work locations in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of work locations to return | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `workLocations` | array | List of work locations | +| ↳ `id` | string | Work location ID | +| ↳ `nickname` | string | Location nickname | +| ↳ `street` | string | Street address | +| ↳ `city` | string | City | +| ↳ `state` | string | State or province | +| ↳ `zip` | string | ZIP or postal code | +| ↳ `country` | string | Country | +| `totalCount` | number | Total number of work locations returned | + +### `rippling_get_company` + +Get details for the current company in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Company ID | +| `name` | string | Company name | +| `address` | json | Company address with street, city, state, zip, country | +| `email` | string | Company email address | +| `phone` | string | Company phone number | +| `workLocations` | array | List of work location IDs | + +### `rippling_get_company_activity` + +Get activity events for the current company in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `startDate` | string | No | Start date filter in ISO format \(e.g. 2024-01-01\) | +| `endDate` | string | No | End date filter in ISO format \(e.g. 2024-12-31\) | +| `limit` | number | No | Maximum number of activity events to return | +| `next` | string | No | Cursor for fetching the next page of results | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `events` | array | List of company activity events | +| ↳ `id` | string | Event ID | +| ↳ `type` | string | Event type | +| ↳ `description` | string | Event description | +| ↳ `createdAt` | string | Event creation timestamp | +| ↳ `actor` | json | Actor who triggered the event \(id, name\) | +| `totalCount` | number | Total number of activity events returned | +| `nextCursor` | string | Cursor for fetching the next page of results | + +### `rippling_list_custom_fields` + +List all custom fields defined in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of custom fields to return | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `customFields` | array | List of custom fields | +| ↳ `id` | string | Custom field ID | +| ↳ `type` | string | Field type | +| ↳ `title` | string | Field title | +| ↳ `mandatory` | boolean | Whether the field is mandatory | +| `totalCount` | number | Total number of custom fields returned | + +### `rippling_get_current_user` + +Get the current authenticated user details + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | User ID | +| `workEmail` | string | Work email address | +| `company` | string | Company ID | + +### `rippling_list_leave_requests` + +List leave requests in Rippling with optional filtering by date range and status + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `startDate` | string | No | Filter by start date \(ISO date string\) | +| `endDate` | string | No | Filter by end date \(ISO date string\) | +| `status` | string | No | Filter by status \(e.g. pending, approved, declined\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `leaveRequests` | array | List of leave requests | +| ↳ `id` | string | Leave request ID | +| ↳ `requestedBy` | string | Employee ID who requested leave | +| ↳ `status` | string | Request status \(pending/approved/declined\) | +| ↳ `startDate` | string | Leave start date | +| ↳ `endDate` | string | Leave end date | +| ↳ `reason` | string | Reason for leave | +| ↳ `leaveType` | string | Type of leave | +| ↳ `createdAt` | string | When the request was created | +| `totalCount` | number | Total number of leave requests returned | + +### `rippling_process_leave_request` + +Approve or decline a leave request in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `leaveRequestId` | string | Yes | The ID of the leave request to process | +| `action` | string | Yes | Action to take on the leave request \(approve or decline\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Leave request ID | +| `status` | string | Updated status of the leave request | +| `requestedBy` | string | Employee ID who requested leave | +| `startDate` | string | Leave start date | +| `endDate` | string | Leave end date | + +### `rippling_list_leave_balances` + +List leave balances for all employees in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `limit` | number | No | Maximum number of leave balances to return | +| `offset` | number | No | Offset for pagination | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `leaveBalances` | array | List of employee leave balances | +| ↳ `employeeId` | string | Employee ID | +| ↳ `balances` | array | Leave balance entries | +| ↳ `leaveType` | string | Type of leave | +| ↳ `minutesRemaining` | number | Minutes of leave remaining | +| `totalCount` | number | Total number of leave balances returned | + +### `rippling_get_leave_balance` + +Get leave balance for a specific employee by role ID + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `roleId` | string | Yes | The employee/role ID to retrieve leave balance for | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `employeeId` | string | Employee ID | +| `balances` | array | Leave balance entries | +| ↳ `leaveType` | string | Type of leave | +| ↳ `minutesRemaining` | number | Minutes of leave remaining | + +### `rippling_list_leave_types` + +List company leave types configured in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `managedBy` | string | No | Filter leave types by manager | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `leaveTypes` | array | List of company leave types | +| ↳ `id` | string | Leave type ID | +| ↳ `name` | string | Leave type name | +| ↳ `managedBy` | string | Manager of this leave type | +| `totalCount` | number | Total number of leave types returned | + +### `rippling_create_group` + +Create a new group in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `name` | string | Yes | Name of the group | +| `spokeId` | string | Yes | Third-party app identifier | +| `users` | json | No | Array of user ID strings to add to the group | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Group ID | +| `name` | string | Group name | +| `spokeId` | string | Third-party app identifier | +| `users` | array | Array of user IDs in the group | +| `version` | number | Group version number | + +### `rippling_update_group` + +Update an existing group in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `groupId` | string | Yes | The ID of the group to update | +| `name` | string | No | New name for the group | +| `spokeId` | string | No | Third-party app identifier | +| `users` | json | No | Array of user ID strings to set for the group | +| `version` | number | No | Group version number for optimistic concurrency | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Group ID | +| `name` | string | Group name | +| `spokeId` | string | Third-party app identifier | +| `users` | array | Array of user IDs in the group | +| `version` | number | Group version number | + +### `rippling_push_candidate` + +Push a candidate to onboarding in Rippling + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Rippling API key | +| `firstName` | string | Yes | Candidate first name | +| `lastName` | string | Yes | Candidate last name | +| `email` | string | Yes | Candidate email address | +| `phone` | string | No | Candidate phone number | +| `jobTitle` | string | No | Job title for the candidate | +| `department` | string | No | Department for the candidate | +| `startDate` | string | No | Start date in ISO 8601 format \(e.g., 2025-01-15\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Candidate ID | +| `firstName` | string | Candidate first name | +| `lastName` | string | Candidate last name | +| `email` | string | Candidate email address | +| `status` | string | Candidate onboarding status | + + diff --git a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts index ef6684838d..fa2c8b75a1 100644 --- a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts +++ b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts @@ -33,8 +33,8 @@ import { DatadogIcon, DevinIcon, DiscordIcon, - DocumentIcon, DocuSignIcon, + DocumentIcon, DropboxIcon, DsPyIcon, DubIcon, @@ -50,8 +50,8 @@ import { FirecrawlIcon, FirefliesIcon, GammaIcon, - GithubIcon, GitLabIcon, + GithubIcon, GmailIcon, GongIcon, GoogleAdsIcon, @@ -95,9 +95,9 @@ import { LinkupIcon, LoopsIcon, LumaIcon, + MailServerIcon, MailchimpIcon, MailgunIcon, - MailServerIcon, Mem0Icon, MicrosoftDataverseIcon, MicrosoftExcelIcon, @@ -133,7 +133,10 @@ import { ReductoIcon, ResendIcon, RevenueCatIcon, + RipplingIcon, S3Icon, + SQSIcon, + STTIcon, SalesforceIcon, SearchIcon, SendgridIcon, @@ -145,19 +148,17 @@ import { SimilarwebIcon, SlackIcon, SmtpIcon, - SQSIcon, SshIcon, - STTIcon, StagehandIcon, StripeIcon, SupabaseIcon, + TTSIcon, TavilyIcon, TelegramIcon, TextractIcon, TinybirdIcon, TranslateIcon, TrelloIcon, - TTSIcon, TwilioIcon, TypeformIcon, UpstashIcon, @@ -169,11 +170,11 @@ import { WikipediaIcon, WordpressIcon, WorkdayIcon, - xIcon, YouTubeIcon, ZendeskIcon, ZepIcon, ZoomIcon, + xIcon, } from '@/components/icons' type IconComponent = ComponentType> @@ -306,6 +307,7 @@ export const blockTypeToIconMap: Record = { reducto_v2: ReductoIcon, resend: ResendIcon, revenuecat: RevenueCatIcon, + rippling: RipplingIcon, s3: S3Icon, salesforce: SalesforceIcon, search: SearchIcon, diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 1905e33e88..a5a69b1588 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -52,7 +52,10 @@ "authType": "api-key", "category": "tools", "integrationType": "security", - "tags": ["secrets-management", "identity"] + "tags": [ + "secrets-management", + "identity" + ] }, { "type": "a2a", @@ -103,7 +106,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["agentic", "automation"] + "tags": [ + "agentic", + "automation" + ] }, { "type": "ahrefs", @@ -154,7 +160,11 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["seo", "marketing", "data-analytics"] + "tags": [ + "seo", + "marketing", + "data-analytics" + ] }, { "type": "airtable", @@ -211,7 +221,10 @@ "authType": "oauth", "category": "tools", "integrationType": "databases", - "tags": ["spreadsheet", "automation"] + "tags": [ + "spreadsheet", + "automation" + ] }, { "type": "airweave", @@ -229,7 +242,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["vector-search", "knowledge-base"] + "tags": [ + "vector-search", + "knowledge-base" + ] }, { "type": "algolia", @@ -308,7 +324,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["vector-search", "knowledge-base"] + "tags": [ + "vector-search", + "knowledge-base" + ] }, { "type": "dynamodb", @@ -355,7 +374,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["cloud", "data-warehouse"] + "tags": [ + "cloud", + "data-warehouse" + ] }, { "type": "rds", @@ -398,7 +420,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["cloud", "data-warehouse"] + "tags": [ + "cloud", + "data-warehouse" + ] }, { "type": "sqs", @@ -421,7 +446,11 @@ "authType": "none", "category": "tools", "integrationType": "developer-tools", - "tags": ["cloud", "messaging", "automation"] + "tags": [ + "cloud", + "messaging", + "automation" + ] }, { "type": "amplitude", @@ -484,7 +513,10 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["data-analytics", "marketing"] + "tags": [ + "data-analytics", + "marketing" + ] }, { "type": "apify", @@ -511,7 +543,11 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": ["web-scraping", "automation", "data-analytics"] + "tags": [ + "web-scraping", + "automation", + "data-analytics" + ] }, { "type": "apollo", @@ -630,7 +666,10 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": ["enrichment", "sales-engagement"] + "tags": [ + "enrichment", + "sales-engagement" + ] }, { "type": "arxiv", @@ -661,7 +700,10 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": ["document-processing", "knowledge-base"] + "tags": [ + "document-processing", + "knowledge-base" + ] }, { "type": "asana", @@ -704,7 +746,11 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["project-management", "ticketing", "automation"] + "tags": [ + "project-management", + "ticketing", + "automation" + ] }, { "type": "ashby", @@ -866,7 +912,9 @@ "authType": "api-key", "category": "tools", "integrationType": "hr", - "tags": ["hiring"] + "tags": [ + "hiring" + ] }, { "type": "attio", @@ -1136,7 +1184,10 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": ["sales-engagement", "enrichment"] + "tags": [ + "sales-engagement", + "enrichment" + ] }, { "type": "textract_v2", @@ -1154,7 +1205,11 @@ "authType": "none", "category": "tools", "integrationType": "ai", - "tags": ["document-processing", "ocr", "cloud"] + "tags": [ + "document-processing", + "ocr", + "cloud" + ] }, { "type": "microsoft_ad", @@ -1225,7 +1280,10 @@ "authType": "oauth", "category": "tools", "integrationType": "security", - "tags": ["identity", "microsoft-365"] + "tags": [ + "identity", + "microsoft-365" + ] }, { "type": "box", @@ -1304,7 +1362,11 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": ["cloud", "content-management", "e-signatures"] + "tags": [ + "cloud", + "content-management", + "e-signatures" + ] }, { "type": "brandfetch", @@ -1331,7 +1393,10 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": ["enrichment", "marketing"] + "tags": [ + "enrichment", + "marketing" + ] }, { "type": "browser_use", @@ -1349,7 +1414,11 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": ["web-scraping", "automation", "agentic"] + "tags": [ + "web-scraping", + "automation", + "agentic" + ] }, { "type": "calcom", @@ -1490,7 +1559,11 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["scheduling", "calendar", "meeting"] + "tags": [ + "scheduling", + "calendar", + "meeting" + ] }, { "type": "calendly", @@ -1558,7 +1631,11 @@ "authType": "api-key", "category": "tools", "integrationType": "productivity", - "tags": ["scheduling", "calendar", "meeting"] + "tags": [ + "scheduling", + "calendar", + "meeting" + ] }, { "type": "circleback", @@ -1592,7 +1669,11 @@ "authType": "none", "category": "triggers", "integrationType": "ai", - "tags": ["meeting", "note-taking", "automation"] + "tags": [ + "meeting", + "note-taking", + "automation" + ] }, { "type": "clay", @@ -1610,7 +1691,11 @@ "authType": "none", "category": "tools", "integrationType": "sales-intelligence", - "tags": ["enrichment", "sales-engagement", "data-analytics"] + "tags": [ + "enrichment", + "sales-engagement", + "data-analytics" + ] }, { "type": "clerk", @@ -1673,7 +1758,10 @@ "authType": "none", "category": "tools", "integrationType": "security", - "tags": ["identity", "automation"] + "tags": [ + "identity", + "automation" + ] }, { "type": "cloudflare", @@ -1744,7 +1832,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["cloud", "monitoring"] + "tags": [ + "cloud", + "monitoring" + ] }, { "type": "confluence_v2", @@ -2028,7 +2119,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["knowledge-base", "content-management", "note-taking"] + "tags": [ + "knowledge-base", + "content-management", + "note-taking" + ] }, { "type": "cursor_v2", @@ -2075,7 +2170,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["agentic", "automation"] + "tags": [ + "agentic", + "automation" + ] }, { "type": "databricks", @@ -2126,7 +2224,11 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": ["data-warehouse", "data-analytics", "cloud"] + "tags": [ + "data-warehouse", + "data-analytics", + "cloud" + ] }, { "type": "datadog", @@ -2193,7 +2295,11 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["monitoring", "incident-management", "error-tracking"] + "tags": [ + "monitoring", + "incident-management", + "error-tracking" + ] }, { "type": "devin", @@ -2228,7 +2334,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["agentic", "automation"] + "tags": [ + "agentic", + "automation" + ] }, { "type": "discord", @@ -2387,7 +2496,11 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "webhooks", "automation"] + "tags": [ + "messaging", + "webhooks", + "automation" + ] }, { "type": "docusign", @@ -2438,7 +2551,10 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["e-signatures", "document-processing"] + "tags": [ + "e-signatures", + "document-processing" + ] }, { "type": "dropbox", @@ -2497,7 +2613,10 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": ["cloud", "document-processing"] + "tags": [ + "cloud", + "document-processing" + ] }, { "type": "dspy", @@ -2528,7 +2647,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "agentic", "automation"] + "tags": [ + "llm", + "agentic", + "automation" + ] }, { "type": "dub", @@ -2575,7 +2698,11 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["link-management", "marketing", "data-analytics"] + "tags": [ + "link-management", + "marketing", + "data-analytics" + ] }, { "type": "duckduckgo", @@ -2593,7 +2720,10 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "seo"] + "tags": [ + "web-scraping", + "seo" + ] }, { "type": "elasticsearch", @@ -2664,7 +2794,10 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": ["vector-search", "data-analytics"] + "tags": [ + "vector-search", + "data-analytics" + ] }, { "type": "elevenlabs", @@ -2682,7 +2815,9 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": ["text-to-speech"] + "tags": [ + "text-to-speech" + ] }, { "type": "openai", @@ -2700,7 +2835,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "vector-search"] + "tags": [ + "llm", + "vector-search" + ] }, { "type": "enrich", @@ -2835,7 +2973,10 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": ["enrichment", "data-analytics"] + "tags": [ + "enrichment", + "data-analytics" + ] }, { "type": "evernote", @@ -2898,7 +3039,10 @@ "authType": "api-key", "category": "tools", "integrationType": "documents", - "tags": ["note-taking", "knowledge-base"] + "tags": [ + "note-taking", + "knowledge-base" + ] }, { "type": "exa", @@ -2937,7 +3081,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "enrichment"] + "tags": [ + "web-scraping", + "enrichment" + ] }, { "type": "fathom", @@ -2987,7 +3134,10 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["meeting", "note-taking"] + "tags": [ + "meeting", + "note-taking" + ] }, { "type": "file_v3", @@ -3005,7 +3155,9 @@ "authType": "none", "category": "tools", "integrationType": "file-storage", - "tags": ["document-processing"] + "tags": [ + "document-processing" + ] }, { "type": "firecrawl", @@ -3048,7 +3200,10 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": ["web-scraping", "automation"] + "tags": [ + "web-scraping", + "automation" + ] }, { "type": "fireflies_v2", @@ -3113,7 +3268,11 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": ["meeting", "speech-to-text", "note-taking"] + "tags": [ + "meeting", + "speech-to-text", + "note-taking" + ] }, { "type": "gamma", @@ -3152,7 +3311,10 @@ "authType": "api-key", "category": "tools", "integrationType": "design", - "tags": ["document-processing", "content-management"] + "tags": [ + "document-processing", + "content-management" + ] }, { "type": "github_v2", @@ -3559,7 +3721,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["version-control", "ci-cd"] + "tags": [ + "version-control", + "ci-cd" + ] }, { "type": "gitlab", @@ -3654,7 +3819,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["version-control", "ci-cd"] + "tags": [ + "version-control", + "ci-cd" + ] }, { "type": "gmail_v2", @@ -3721,7 +3889,10 @@ "authType": "oauth", "category": "tools", "integrationType": "email", - "tags": ["google-workspace", "messaging"] + "tags": [ + "google-workspace", + "messaging" + ] }, { "type": "gong", @@ -3812,7 +3983,11 @@ "authType": "none", "category": "tools", "integrationType": "sales-intelligence", - "tags": ["meeting", "sales-engagement", "speech-to-text"] + "tags": [ + "meeting", + "sales-engagement", + "speech-to-text" + ] }, { "type": "google_ads", @@ -3855,7 +4030,11 @@ "authType": "oauth", "category": "tools", "integrationType": "analytics", - "tags": ["marketing", "google-workspace", "data-analytics"] + "tags": [ + "marketing", + "google-workspace", + "data-analytics" + ] }, { "type": "google_bigquery", @@ -3894,7 +4073,11 @@ "authType": "oauth", "category": "tools", "integrationType": "databases", - "tags": ["data-warehouse", "google-workspace", "data-analytics"] + "tags": [ + "data-warehouse", + "google-workspace", + "data-analytics" + ] }, { "type": "google_books", @@ -3921,7 +4104,11 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["google-workspace", "knowledge-base", "content-management"] + "tags": [ + "google-workspace", + "knowledge-base", + "content-management" + ] }, { "type": "google_calendar_v2", @@ -3980,7 +4167,11 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["calendar", "scheduling", "google-workspace"] + "tags": [ + "calendar", + "scheduling", + "google-workspace" + ] }, { "type": "google_contacts", @@ -4023,7 +4214,11 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["google-workspace", "customer-support", "enrichment"] + "tags": [ + "google-workspace", + "customer-support", + "enrichment" + ] }, { "type": "google_docs", @@ -4054,7 +4249,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["google-workspace", "document-processing", "content-management"] + "tags": [ + "google-workspace", + "document-processing", + "content-management" + ] }, { "type": "google_drive", @@ -4129,7 +4328,11 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": ["cloud", "google-workspace", "document-processing"] + "tags": [ + "cloud", + "google-workspace", + "document-processing" + ] }, { "type": "google_forms", @@ -4190,7 +4393,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["google-workspace", "forms", "data-analytics"] + "tags": [ + "google-workspace", + "forms", + "data-analytics" + ] }, { "type": "google_groups", @@ -4273,7 +4480,11 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": ["google-workspace", "messaging", "identity"] + "tags": [ + "google-workspace", + "messaging", + "identity" + ] }, { "type": "google_maps", @@ -4344,7 +4555,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["google-workspace", "enrichment"] + "tags": [ + "google-workspace", + "enrichment" + ] }, { "type": "google_meet", @@ -4387,7 +4601,11 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": ["meeting", "google-workspace", "scheduling"] + "tags": [ + "meeting", + "google-workspace", + "scheduling" + ] }, { "type": "google_pagespeed", @@ -4405,7 +4623,11 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["google-workspace", "seo", "monitoring"] + "tags": [ + "google-workspace", + "seo", + "monitoring" + ] }, { "type": "google_search", @@ -4423,7 +4645,11 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["google-workspace", "web-scraping", "seo"] + "tags": [ + "google-workspace", + "web-scraping", + "seo" + ] }, { "type": "google_sheets_v2", @@ -4486,7 +4712,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["spreadsheet", "google-workspace", "data-analytics"] + "tags": [ + "spreadsheet", + "google-workspace", + "data-analytics" + ] }, { "type": "google_slides_v2", @@ -4561,7 +4791,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["google-workspace", "document-processing", "content-management"] + "tags": [ + "google-workspace", + "document-processing", + "content-management" + ] }, { "type": "google_tasks", @@ -4604,7 +4838,11 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["google-workspace", "project-management", "scheduling"] + "tags": [ + "google-workspace", + "project-management", + "scheduling" + ] }, { "type": "google_translate", @@ -4631,7 +4869,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["google-workspace", "content-management", "automation"] + "tags": [ + "google-workspace", + "content-management", + "automation" + ] }, { "type": "google_vault", @@ -4678,7 +4920,11 @@ "authType": "oauth", "category": "tools", "integrationType": "security", - "tags": ["google-workspace", "secrets-management", "document-processing"] + "tags": [ + "google-workspace", + "secrets-management", + "document-processing" + ] }, { "type": "grafana", @@ -4773,7 +5019,10 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["monitoring", "data-analytics"] + "tags": [ + "monitoring", + "data-analytics" + ] }, { "type": "grain", @@ -4869,7 +5118,10 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": ["meeting", "note-taking"] + "tags": [ + "meeting", + "note-taking" + ] }, { "type": "greenhouse", @@ -4932,7 +5184,9 @@ "authType": "api-key", "category": "tools", "integrationType": "hr", - "tags": ["hiring"] + "tags": [ + "hiring" + ] }, { "type": "greptile", @@ -4967,7 +5221,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["version-control", "knowledge-base"] + "tags": [ + "version-control", + "knowledge-base" + ] }, { "type": "hex", @@ -5050,7 +5307,10 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["data-warehouse", "data-analytics"] + "tags": [ + "data-warehouse", + "data-analytics" + ] }, { "type": "hubspot", @@ -5200,7 +5460,11 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": ["marketing", "sales-engagement", "customer-support"] + "tags": [ + "marketing", + "sales-engagement", + "customer-support" + ] }, { "type": "huggingface", @@ -5218,7 +5482,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "agentic"] + "tags": [ + "llm", + "agentic" + ] }, { "type": "hunter", @@ -5261,7 +5528,10 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": ["enrichment", "sales-engagement"] + "tags": [ + "enrichment", + "sales-engagement" + ] }, { "type": "image_generator", @@ -5279,7 +5549,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["image-generation", "llm"] + "tags": [ + "image-generation", + "llm" + ] }, { "type": "imap", @@ -5303,7 +5576,10 @@ "authType": "none", "category": "triggers", "integrationType": "email", - "tags": ["messaging", "automation"] + "tags": [ + "messaging", + "automation" + ] }, { "type": "incidentio", @@ -5498,7 +5774,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["incident-management", "monitoring"] + "tags": [ + "incident-management", + "monitoring" + ] }, { "type": "infisical", @@ -5537,7 +5816,9 @@ "authType": "api-key", "category": "tools", "integrationType": "security", - "tags": ["secrets-management"] + "tags": [ + "secrets-management" + ] }, { "type": "intercom_v2", @@ -5680,7 +5961,10 @@ "authType": "api-key", "category": "tools", "integrationType": "customer-support", - "tags": ["customer-support", "messaging"] + "tags": [ + "customer-support", + "messaging" + ] }, { "type": "jina", @@ -5707,7 +5991,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "knowledge-base"] + "tags": [ + "web-scraping", + "knowledge-base" + ] }, { "type": "jira", @@ -5853,7 +6140,10 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["project-management", "ticketing"] + "tags": [ + "project-management", + "ticketing" + ] }, { "type": "jira_service_management", @@ -5956,7 +6246,11 @@ "authType": "oauth", "category": "tools", "integrationType": "customer-support", - "tags": ["customer-support", "ticketing", "incident-management"] + "tags": [ + "customer-support", + "ticketing", + "incident-management" + ] }, { "type": "kalshi_v2", @@ -6043,7 +6337,10 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": ["prediction-markets", "data-analytics"] + "tags": [ + "prediction-markets", + "data-analytics" + ] }, { "type": "knowledge", @@ -6143,7 +6440,11 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["monitoring", "llm", "data-analytics"] + "tags": [ + "monitoring", + "llm", + "data-analytics" + ] }, { "type": "lemlist", @@ -6220,7 +6521,11 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": ["sales-engagement", "email-marketing", "automation"] + "tags": [ + "sales-engagement", + "email-marketing", + "automation" + ] }, { "type": "linear", @@ -6627,7 +6932,10 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["project-management", "ticketing"] + "tags": [ + "project-management", + "ticketing" + ] }, { "type": "linkedin", @@ -6654,7 +6962,11 @@ "authType": "oauth", "category": "tools", "integrationType": "social", - "tags": ["marketing", "sales-engagement", "enrichment"] + "tags": [ + "marketing", + "sales-engagement", + "enrichment" + ] }, { "type": "linkup", @@ -6672,7 +6984,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "enrichment"] + "tags": [ + "web-scraping", + "enrichment" + ] }, { "type": "loops", @@ -6731,7 +7046,11 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": ["email-marketing", "marketing", "automation"] + "tags": [ + "email-marketing", + "marketing", + "automation" + ] }, { "type": "luma", @@ -6774,7 +7093,11 @@ "authType": "api-key", "category": "tools", "integrationType": "productivity", - "tags": ["events", "calendar", "scheduling"] + "tags": [ + "events", + "calendar", + "scheduling" + ] }, { "type": "mailchimp", @@ -7085,7 +7408,11 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": ["email-marketing", "marketing", "automation"] + "tags": [ + "email-marketing", + "marketing", + "automation" + ] }, { "type": "mailgun", @@ -7136,7 +7463,10 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": ["messaging", "email-marketing"] + "tags": [ + "messaging", + "email-marketing" + ] }, { "type": "mem0", @@ -7167,7 +7497,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "knowledge-base", "agentic"] + "tags": [ + "llm", + "knowledge-base", + "agentic" + ] }, { "type": "memory", @@ -7287,7 +7621,11 @@ "authType": "oauth", "category": "tools", "integrationType": "databases", - "tags": ["microsoft-365", "data-warehouse", "cloud"] + "tags": [ + "microsoft-365", + "data-warehouse", + "cloud" + ] }, { "type": "microsoft_excel_v2", @@ -7314,7 +7652,10 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["spreadsheet", "microsoft-365"] + "tags": [ + "spreadsheet", + "microsoft-365" + ] }, { "type": "microsoft_planner", @@ -7385,7 +7726,11 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["project-management", "microsoft-365", "ticketing"] + "tags": [ + "project-management", + "microsoft-365", + "ticketing" + ] }, { "type": "microsoft_teams", @@ -7466,7 +7811,10 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "microsoft-365"] + "tags": [ + "messaging", + "microsoft-365" + ] }, { "type": "mistral_parse_v3", @@ -7484,7 +7832,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["document-processing", "ocr"] + "tags": [ + "document-processing", + "ocr" + ] }, { "type": "mongodb", @@ -7527,7 +7878,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["data-warehouse", "cloud"] + "tags": [ + "data-warehouse", + "cloud" + ] }, { "type": "mysql", @@ -7570,7 +7924,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["data-warehouse", "data-analytics"] + "tags": [ + "data-warehouse", + "data-analytics" + ] }, { "type": "neo4j", @@ -7617,7 +7974,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["data-warehouse", "data-analytics"] + "tags": [ + "data-warehouse", + "data-analytics" + ] }, { "type": "notion_v2", @@ -7635,7 +7995,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["note-taking", "knowledge-base", "content-management"] + "tags": [ + "note-taking", + "knowledge-base", + "content-management" + ] }, { "type": "obsidian", @@ -7714,7 +8078,10 @@ "authType": "api-key", "category": "tools", "integrationType": "documents", - "tags": ["note-taking", "knowledge-base"] + "tags": [ + "note-taking", + "knowledge-base" + ] }, { "type": "okta", @@ -7805,7 +8172,10 @@ "authType": "api-key", "category": "tools", "integrationType": "security", - "tags": ["identity", "automation"] + "tags": [ + "identity", + "automation" + ] }, { "type": "onedrive", @@ -7848,7 +8218,11 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": ["microsoft-365", "cloud", "document-processing"] + "tags": [ + "microsoft-365", + "cloud", + "document-processing" + ] }, { "type": "outlook", @@ -7903,7 +8277,11 @@ "authType": "oauth", "category": "tools", "integrationType": "email", - "tags": ["microsoft-365", "messaging", "automation"] + "tags": [ + "microsoft-365", + "messaging", + "automation" + ] }, { "type": "pagerduty", @@ -7946,7 +8324,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["incident-management", "monitoring"] + "tags": [ + "incident-management", + "monitoring" + ] }, { "type": "parallel_ai", @@ -7977,7 +8358,11 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "llm", "agentic"] + "tags": [ + "web-scraping", + "llm", + "agentic" + ] }, { "type": "perplexity", @@ -8004,7 +8389,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "web-scraping", "agentic"] + "tags": [ + "llm", + "web-scraping", + "agentic" + ] }, { "type": "pinecone", @@ -8043,7 +8432,10 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": ["vector-search", "knowledge-base"] + "tags": [ + "vector-search", + "knowledge-base" + ] }, { "type": "pipedrive", @@ -8134,7 +8526,10 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": ["sales-engagement", "project-management"] + "tags": [ + "sales-engagement", + "project-management" + ] }, { "type": "polymarket", @@ -8233,7 +8628,10 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": ["prediction-markets", "data-analytics"] + "tags": [ + "prediction-markets", + "data-analytics" + ] }, { "type": "postgresql", @@ -8276,7 +8674,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["data-warehouse", "data-analytics"] + "tags": [ + "data-warehouse", + "data-analytics" + ] }, { "type": "posthog", @@ -8467,7 +8868,10 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": ["data-analytics", "monitoring"] + "tags": [ + "data-analytics", + "monitoring" + ] }, { "type": "pulse_v2", @@ -8485,7 +8889,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["document-processing", "ocr"] + "tags": [ + "document-processing", + "ocr" + ] }, { "type": "qdrant", @@ -8516,7 +8923,10 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": ["vector-search", "knowledge-base"] + "tags": [ + "vector-search", + "knowledge-base" + ] }, { "type": "quiver", @@ -8547,7 +8957,9 @@ "authType": "api-key", "category": "tools", "integrationType": "design", - "tags": ["image-generation"] + "tags": [ + "image-generation" + ] }, { "type": "reddit", @@ -8634,7 +9046,10 @@ "authType": "oauth", "category": "tools", "integrationType": "social", - "tags": ["content-management", "web-scraping"] + "tags": [ + "content-management", + "web-scraping" + ] }, { "type": "redis", @@ -8741,7 +9156,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["cloud", "data-warehouse"] + "tags": [ + "cloud", + "data-warehouse" + ] }, { "type": "reducto_v2", @@ -8759,7 +9177,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["document-processing", "ocr"] + "tags": [ + "document-processing", + "ocr" + ] }, { "type": "resend", @@ -8810,7 +9231,10 @@ "authType": "none", "category": "tools", "integrationType": "email", - "tags": ["email-marketing", "messaging"] + "tags": [ + "email-marketing", + "messaging" + ] }, { "type": "revenuecat", @@ -8869,7 +9293,104 @@ "authType": "api-key", "category": "tools", "integrationType": "ecommerce", - "tags": ["payments", "subscriptions"] + "tags": [ + "payments", + "subscriptions" + ] + }, + { + "type": "rippling", + "slug": "rippling", + "name": "Rippling", + "description": "Manage employees, leave, departments, and company data in Rippling", + "longDescription": "Integrate Rippling into your workflow. Manage employees, departments, teams, leave requests, work locations, groups, candidates, and company information.", + "bgColor": "#FFCC1C", + "iconName": "RipplingIcon", + "docsUrl": "https://docs.sim.ai/tools/rippling", + "operations": [ + { + "name": "List Employees", + "description": "List all employees in Rippling with optional pagination" + }, + { + "name": "Get Employee", + "description": "Get details for a specific employee by ID" + }, + { + "name": "List Employees (Including Terminated)", + "description": "List all employees in Rippling including terminated employees with optional pagination" + }, + { + "name": "List Departments", + "description": "List all departments in the Rippling organization" + }, + { + "name": "List Teams", + "description": "List all teams in Rippling" + }, + { + "name": "List Levels", + "description": "List all position levels in Rippling" + }, + { + "name": "List Work Locations", + "description": "List all work locations in Rippling" + }, + { + "name": "Get Company", + "description": "Get details for the current company in Rippling" + }, + { + "name": "Get Company Activity", + "description": "Get activity events for the current company in Rippling" + }, + { + "name": "List Custom Fields", + "description": "List all custom fields defined in Rippling" + }, + { + "name": "Get Current User", + "description": "Get the current authenticated user details" + }, + { + "name": "List Leave Requests", + "description": "List leave requests in Rippling with optional filtering by date range and status" + }, + { + "name": "Approve/Decline Leave Request", + "description": "Approve or decline a leave request in Rippling" + }, + { + "name": "List Leave Balances", + "description": "List leave balances for all employees in Rippling" + }, + { + "name": "Get Leave Balance", + "description": "Get leave balance for a specific employee by role ID" + }, + { + "name": "List Leave Types", + "description": "" + }, + { + "name": "Create Group", + "description": "Create a new group in Rippling" + }, + { + "name": "Update Group", + "description": "Update an existing group in Rippling" + }, + { + "name": "Push Candidate", + "description": "Push a candidate to onboarding in Rippling" + } + ], + "operationCount": 19, + "triggers": [], + "triggerCount": 0, + "authType": "api-key", + "category": "tools", + "integrationType": "hr" }, { "type": "s3", @@ -8908,7 +9429,10 @@ "authType": "none", "category": "tools", "integrationType": "file-storage", - "tags": ["cloud", "data-warehouse"] + "tags": [ + "cloud", + "data-warehouse" + ] }, { "type": "salesforce", @@ -9067,7 +9591,10 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": ["sales-engagement", "customer-support"] + "tags": [ + "sales-engagement", + "customer-support" + ] }, { "type": "search", @@ -9085,7 +9612,10 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "seo"] + "tags": [ + "web-scraping", + "seo" + ] }, { "type": "sendgrid", @@ -9168,7 +9698,10 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": ["email-marketing", "messaging"] + "tags": [ + "email-marketing", + "messaging" + ] }, { "type": "sentry", @@ -9235,7 +9768,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["error-tracking", "monitoring"] + "tags": [ + "error-tracking", + "monitoring" + ] }, { "type": "serper", @@ -9253,7 +9789,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "seo"] + "tags": [ + "web-scraping", + "seo" + ] }, { "type": "servicenow", @@ -9288,7 +9827,11 @@ "authType": "none", "category": "tools", "integrationType": "customer-support", - "tags": ["customer-support", "ticketing", "incident-management"] + "tags": [ + "customer-support", + "ticketing", + "incident-management" + ] }, { "type": "sftp", @@ -9331,7 +9874,10 @@ "authType": "none", "category": "tools", "integrationType": "file-storage", - "tags": ["cloud", "automation"] + "tags": [ + "cloud", + "automation" + ] }, { "type": "sharepoint", @@ -9382,7 +9928,11 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": ["microsoft-365", "content-management", "document-processing"] + "tags": [ + "microsoft-365", + "content-management", + "document-processing" + ] }, { "type": "shopify", @@ -9485,7 +10035,10 @@ "authType": "oauth", "category": "tools", "integrationType": "ecommerce", - "tags": ["payments", "subscriptions"] + "tags": [ + "payments", + "subscriptions" + ] }, { "type": "similarweb", @@ -9524,7 +10077,11 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": ["marketing", "data-analytics", "seo"] + "tags": [ + "marketing", + "data-analytics", + "seo" + ] }, { "type": "slack", @@ -9649,7 +10206,11 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "webhooks", "automation"] + "tags": [ + "messaging", + "webhooks", + "automation" + ] }, { "type": "smtp", @@ -9667,7 +10228,10 @@ "authType": "none", "category": "tools", "integrationType": "email", - "tags": ["email-marketing", "messaging"] + "tags": [ + "email-marketing", + "messaging" + ] }, { "type": "stt_v2", @@ -9685,7 +10249,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["speech-to-text", "document-processing"] + "tags": [ + "speech-to-text", + "document-processing" + ] }, { "type": "ssh", @@ -9756,7 +10323,10 @@ "authType": "none", "category": "tools", "integrationType": "developer-tools", - "tags": ["cloud", "automation"] + "tags": [ + "cloud", + "automation" + ] }, { "type": "stagehand", @@ -9783,7 +10353,11 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": ["web-scraping", "automation", "agentic"] + "tags": [ + "web-scraping", + "automation", + "agentic" + ] }, { "type": "stripe", @@ -10008,7 +10582,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ecommerce", - "tags": ["payments", "subscriptions", "webhooks"] + "tags": [ + "payments", + "subscriptions", + "webhooks" + ] }, { "type": "supabase", @@ -10115,7 +10693,11 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": ["cloud", "data-warehouse", "vector-search"] + "tags": [ + "cloud", + "data-warehouse", + "vector-search" + ] }, { "type": "tavily", @@ -10150,7 +10732,10 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": ["web-scraping", "enrichment"] + "tags": [ + "web-scraping", + "enrichment" + ] }, { "type": "telegram", @@ -10203,7 +10788,11 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "webhooks", "automation"] + "tags": [ + "messaging", + "webhooks", + "automation" + ] }, { "type": "tts", @@ -10221,7 +10810,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["text-to-speech", "llm"] + "tags": [ + "text-to-speech", + "llm" + ] }, { "type": "tinybird", @@ -10248,7 +10840,10 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": ["data-warehouse", "data-analytics"] + "tags": [ + "data-warehouse", + "data-analytics" + ] }, { "type": "translate", @@ -10266,7 +10861,10 @@ "authType": "none", "category": "tools", "integrationType": "ai", - "tags": ["document-processing", "llm"] + "tags": [ + "document-processing", + "llm" + ] }, { "type": "trello", @@ -10309,7 +10907,10 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": ["project-management", "ticketing"] + "tags": [ + "project-management", + "ticketing" + ] }, { "type": "twilio_sms", @@ -10327,7 +10928,10 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "automation"] + "tags": [ + "messaging", + "automation" + ] }, { "type": "twilio_voice", @@ -10364,7 +10968,10 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "text-to-speech"] + "tags": [ + "messaging", + "text-to-speech" + ] }, { "type": "typeform", @@ -10421,7 +11028,10 @@ "authType": "api-key", "category": "tools", "integrationType": "documents", - "tags": ["forms", "data-analytics"] + "tags": [ + "forms", + "data-analytics" + ] }, { "type": "upstash", @@ -10504,7 +11114,10 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": ["cloud", "data-warehouse"] + "tags": [ + "cloud", + "data-warehouse" + ] }, { "type": "vercel", @@ -10723,7 +11336,10 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": ["cloud", "ci-cd"] + "tags": [ + "cloud", + "ci-cd" + ] }, { "type": "video_generator_v2", @@ -10741,7 +11357,10 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["video-generation", "llm"] + "tags": [ + "video-generation", + "llm" + ] }, { "type": "vision_v2", @@ -10759,7 +11378,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "document-processing", "ocr"] + "tags": [ + "llm", + "document-processing", + "ocr" + ] }, { "type": "wealthbox", @@ -10802,7 +11425,10 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": ["sales-engagement", "customer-support"] + "tags": [ + "sales-engagement", + "customer-support" + ] }, { "type": "webflow", @@ -10862,7 +11488,10 @@ "authType": "oauth", "category": "tools", "integrationType": "design", - "tags": ["content-management", "seo"] + "tags": [ + "content-management", + "seo" + ] }, { "type": "whatsapp", @@ -10886,7 +11515,10 @@ "authType": "api-key", "category": "tools", "integrationType": "communication", - "tags": ["messaging", "automation"] + "tags": [ + "messaging", + "automation" + ] }, { "type": "wikipedia", @@ -10921,7 +11553,10 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": ["knowledge-base", "web-scraping"] + "tags": [ + "knowledge-base", + "web-scraping" + ] }, { "type": "wordpress", @@ -11044,7 +11679,10 @@ "authType": "oauth", "category": "tools", "integrationType": "design", - "tags": ["content-management", "seo"] + "tags": [ + "content-management", + "seo" + ] }, { "type": "workday", @@ -11103,7 +11741,10 @@ "authType": "none", "category": "tools", "integrationType": "hr", - "tags": ["hiring", "project-management"] + "tags": [ + "hiring", + "project-management" + ] }, { "type": "x", @@ -11234,7 +11875,10 @@ "authType": "oauth", "category": "tools", "integrationType": "social", - "tags": ["marketing", "messaging"] + "tags": [ + "marketing", + "messaging" + ] }, { "type": "youtube", @@ -11289,7 +11933,11 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": ["google-workspace", "marketing", "content-management"] + "tags": [ + "google-workspace", + "marketing", + "content-management" + ] }, { "type": "zendesk", @@ -11412,7 +12060,10 @@ "authType": "none", "category": "tools", "integrationType": "customer-support", - "tags": ["customer-support", "ticketing"] + "tags": [ + "customer-support", + "ticketing" + ] }, { "type": "zep", @@ -11467,7 +12118,11 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": ["llm", "knowledge-base", "agentic"] + "tags": [ + "llm", + "knowledge-base", + "agentic" + ] }, { "type": "zoom", @@ -11526,6 +12181,10 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": ["meeting", "calendar", "scheduling"] + "tags": [ + "meeting", + "calendar", + "scheduling" + ] } -] +] \ No newline at end of file diff --git a/apps/sim/blocks/blocks/rippling.ts b/apps/sim/blocks/blocks/rippling.ts new file mode 100644 index 0000000000..c4a4b8a2a1 --- /dev/null +++ b/apps/sim/blocks/blocks/rippling.ts @@ -0,0 +1,406 @@ +import { RipplingIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode, IntegrationType } from '@/blocks/types' + +export const RipplingBlock: BlockConfig = { + type: 'rippling', + name: 'Rippling', + description: 'Manage employees, leave, departments, and company data in Rippling', + longDescription: + 'Integrate Rippling into your workflow. Manage employees, departments, teams, leave requests, work locations, groups, candidates, and company information.', + docsLink: 'https://docs.sim.ai/tools/rippling', + category: 'tools', + integrationType: IntegrationType.HR, + tags: [], + bgColor: '#FFCC1C', + icon: RipplingIcon, + authMode: AuthMode.ApiKey, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'List Employees', id: 'list_employees' }, + { label: 'Get Employee', id: 'get_employee' }, + { label: 'List Employees (Including Terminated)', id: 'list_employees_with_terminated' }, + { label: 'List Departments', id: 'list_departments' }, + { label: 'List Teams', id: 'list_teams' }, + { label: 'List Levels', id: 'list_levels' }, + { label: 'List Work Locations', id: 'list_work_locations' }, + { label: 'Get Company', id: 'get_company' }, + { label: 'Get Company Activity', id: 'get_company_activity' }, + { label: 'List Custom Fields', id: 'list_custom_fields' }, + { label: 'Get Current User', id: 'get_current_user' }, + { label: 'List Leave Requests', id: 'list_leave_requests' }, + { label: 'Approve/Decline Leave Request', id: 'process_leave_request' }, + { label: 'List Leave Balances', id: 'list_leave_balances' }, + { label: 'Get Leave Balance', id: 'get_leave_balance' }, + { label: 'List Leave Types', id: 'list_leave_types' }, + { label: 'Create Group', id: 'create_group' }, + { label: 'Update Group', id: 'update_group' }, + { label: 'Push Candidate', id: 'push_candidate' }, + ], + value: () => 'list_employees', + }, + // Employee ID - for get_employee + { + id: 'employeeId', + title: 'Employee ID', + type: 'short-input', + placeholder: 'Enter the employee ID', + required: { field: 'operation', value: 'get_employee' }, + condition: { field: 'operation', value: 'get_employee' }, + }, + // Leave Request fields + { + id: 'leaveRequestId', + title: 'Leave Request ID', + type: 'short-input', + placeholder: 'Enter the leave request ID', + required: { field: 'operation', value: 'process_leave_request' }, + condition: { field: 'operation', value: 'process_leave_request' }, + }, + { + id: 'action', + title: 'Action', + type: 'dropdown', + options: [ + { label: 'Approve', id: 'approve' }, + { label: 'Decline', id: 'decline' }, + ], + value: () => 'approve', + required: { field: 'operation', value: 'process_leave_request' }, + condition: { field: 'operation', value: 'process_leave_request' }, + }, + // Leave balance - role ID + { + id: 'roleId', + title: 'Employee/Role ID', + type: 'short-input', + placeholder: 'Enter the employee or role ID', + required: { field: 'operation', value: 'get_leave_balance' }, + condition: { field: 'operation', value: 'get_leave_balance' }, + }, + // Group fields + { + id: 'groupName', + title: 'Group Name', + type: 'short-input', + placeholder: 'Enter group name', + required: { field: 'operation', value: 'create_group' }, + condition: { field: 'operation', value: ['create_group', 'update_group'] }, + }, + { + id: 'spokeId', + title: 'Spoke ID', + type: 'short-input', + placeholder: 'Third-party app identifier', + required: { field: 'operation', value: 'create_group' }, + condition: { field: 'operation', value: ['create_group', 'update_group'] }, + }, + { + id: 'groupId', + title: 'Group ID', + type: 'short-input', + placeholder: 'Enter the group ID to update', + required: { field: 'operation', value: 'update_group' }, + condition: { field: 'operation', value: 'update_group' }, + }, + { + id: 'users', + title: 'User IDs', + type: 'long-input', + placeholder: '["user-id-1", "user-id-2"]', + mode: 'advanced', + condition: { field: 'operation', value: ['create_group', 'update_group'] }, + }, + { + id: 'groupVersion', + title: 'Version', + type: 'short-input', + placeholder: 'Group version number', + mode: 'advanced', + condition: { field: 'operation', value: 'update_group' }, + }, + // Candidate fields + { + id: 'firstName', + title: 'First Name', + type: 'short-input', + placeholder: 'Candidate first name', + required: { field: 'operation', value: 'push_candidate' }, + condition: { field: 'operation', value: 'push_candidate' }, + }, + { + id: 'lastName', + title: 'Last Name', + type: 'short-input', + placeholder: 'Candidate last name', + required: { field: 'operation', value: 'push_candidate' }, + condition: { field: 'operation', value: 'push_candidate' }, + }, + { + id: 'email', + title: 'Email', + type: 'short-input', + placeholder: 'Candidate email address', + required: { field: 'operation', value: 'push_candidate' }, + condition: { field: 'operation', value: 'push_candidate' }, + }, + { + id: 'candidatePhone', + title: 'Phone', + type: 'short-input', + placeholder: 'Candidate phone number', + mode: 'advanced', + condition: { field: 'operation', value: 'push_candidate' }, + }, + { + id: 'jobTitle', + title: 'Job Title', + type: 'short-input', + placeholder: 'Job title for the candidate', + mode: 'advanced', + condition: { field: 'operation', value: 'push_candidate' }, + }, + { + id: 'candidateDepartment', + title: 'Department', + type: 'short-input', + placeholder: 'Department for the candidate', + mode: 'advanced', + condition: { field: 'operation', value: 'push_candidate' }, + }, + { + id: 'candidateStartDate', + title: 'Start Date', + type: 'short-input', + placeholder: 'YYYY-MM-DD', + mode: 'advanced', + condition: { field: 'operation', value: 'push_candidate' }, + wandConfig: { + enabled: true, + prompt: + 'Generate a date in YYYY-MM-DD format for a candidate start date. Return ONLY the date string - no explanations, no extra text.', + generationType: 'timestamp', + }, + }, + // Date filters for leave requests and company activity + { + id: 'startDate', + title: 'Start Date', + type: 'short-input', + placeholder: 'YYYY-MM-DD', + mode: 'advanced', + condition: { field: 'operation', value: ['list_leave_requests', 'get_company_activity'] }, + wandConfig: { + enabled: true, + prompt: + 'Generate a date in YYYY-MM-DD format for filtering by start date. Return ONLY the date string - no explanations, no extra text.', + generationType: 'timestamp', + }, + }, + { + id: 'endDate', + title: 'End Date', + type: 'short-input', + placeholder: 'YYYY-MM-DD', + mode: 'advanced', + condition: { field: 'operation', value: ['list_leave_requests', 'get_company_activity'] }, + wandConfig: { + enabled: true, + prompt: + 'Generate a date in YYYY-MM-DD format for filtering by end date. Return ONLY the date string - no explanations, no extra text.', + generationType: 'timestamp', + }, + }, + { + id: 'status', + title: 'Status Filter', + type: 'short-input', + placeholder: 'e.g., pending, approved, declined', + mode: 'advanced', + condition: { field: 'operation', value: 'list_leave_requests' }, + }, + { + id: 'managedBy', + title: 'Managed By', + type: 'short-input', + placeholder: 'Filter by manager', + mode: 'advanced', + condition: { field: 'operation', value: 'list_leave_types' }, + }, + // Pagination - shared across list operations (offset-based) + { + id: 'limit', + title: 'Limit', + type: 'short-input', + placeholder: '100', + mode: 'advanced', + condition: { + field: 'operation', + value: [ + 'list_employees', + 'list_employees_with_terminated', + 'list_departments', + 'list_teams', + 'list_levels', + 'list_work_locations', + 'list_custom_fields', + 'list_leave_balances', + 'get_company_activity', + ], + }, + }, + { + id: 'offset', + title: 'Offset', + type: 'short-input', + placeholder: '0', + mode: 'advanced', + condition: { + field: 'operation', + value: [ + 'list_employees', + 'list_employees_with_terminated', + 'list_departments', + 'list_teams', + 'list_levels', + 'list_work_locations', + 'list_custom_fields', + 'list_leave_balances', + ], + }, + }, + // Cursor-based pagination for company activity + { + id: 'nextCursor', + title: 'Next Page Cursor', + type: 'short-input', + placeholder: 'Cursor from previous response', + mode: 'advanced', + condition: { field: 'operation', value: 'get_company_activity' }, + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your Rippling API key', + required: true, + password: true, + }, + ], + + tools: { + access: [ + 'rippling_list_employees', + 'rippling_get_employee', + 'rippling_list_employees_with_terminated', + 'rippling_list_departments', + 'rippling_list_teams', + 'rippling_list_levels', + 'rippling_list_work_locations', + 'rippling_get_company', + 'rippling_get_company_activity', + 'rippling_list_custom_fields', + 'rippling_get_current_user', + 'rippling_list_leave_requests', + 'rippling_process_leave_request', + 'rippling_list_leave_balances', + 'rippling_get_leave_balance', + 'rippling_list_leave_types', + 'rippling_create_group', + 'rippling_update_group', + 'rippling_push_candidate', + ], + config: { + tool: (params) => `rippling_${params.operation}`, + params: (params) => ({ + ...params, + ...(params.limit && { limit: Number(params.limit) }), + ...(params.offset && { offset: Number(params.offset) }), + ...(params.groupVersion && { version: Number(params.groupVersion) }), + ...(params.groupName && { name: params.groupName }), + ...(params.candidatePhone && { phone: params.candidatePhone }), + ...(params.candidateDepartment && { department: params.candidateDepartment }), + ...(params.candidateStartDate && { startDate: params.candidateStartDate }), + ...(params.nextCursor && { next: params.nextCursor }), + ...(params.users && { + users: typeof params.users === 'string' ? JSON.parse(params.users) : params.users, + }), + }), + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + employeeId: { type: 'string', description: 'Employee ID' }, + leaveRequestId: { type: 'string', description: 'Leave request ID' }, + action: { type: 'string', description: 'Action to take (approve or decline)' }, + roleId: { type: 'string', description: 'Employee/role ID for leave balance' }, + groupName: { type: 'string', description: 'Group name' }, + spokeId: { type: 'string', description: 'Third-party app identifier' }, + groupId: { type: 'string', description: 'Group ID to update' }, + users: { type: 'json', description: 'Array of user IDs' }, + firstName: { type: 'string', description: 'Candidate first name' }, + lastName: { type: 'string', description: 'Candidate last name' }, + email: { type: 'string', description: 'Candidate email' }, + candidatePhone: { type: 'string', description: 'Candidate phone number' }, + jobTitle: { type: 'string', description: 'Job title' }, + candidateDepartment: { type: 'string', description: 'Department' }, + candidateStartDate: { type: 'string', description: 'Start date (ISO format)' }, + startDate: { type: 'string', description: 'Filter start date' }, + endDate: { type: 'string', description: 'Filter end date' }, + status: { type: 'string', description: 'Leave request status filter' }, + managedBy: { type: 'string', description: 'Filter leave types by manager' }, + limit: { type: 'number', description: 'Maximum number of results' }, + offset: { type: 'number', description: 'Pagination offset' }, + nextCursor: { type: 'string', description: 'Cursor for next page (company activity)' }, + apiKey: { type: 'string', description: 'Rippling API key' }, + }, + + outputs: { + employees: { + type: 'array', + description: + 'List of employees (id, firstName, lastName, workEmail, roleState, department, title)', + }, + departments: { type: 'array', description: 'List of departments (id, name, parent)' }, + teams: { type: 'array', description: 'List of teams (id, name, parent)' }, + levels: { type: 'array', description: 'List of position levels (id, name, parent)' }, + workLocations: { + type: 'array', + description: 'List of work locations (id, nickname, street, city, state, zip, country)', + }, + customFields: { + type: 'array', + description: 'List of custom fields (id, type, title, mandatory)', + }, + events: { + type: 'array', + description: 'List of company activity events (id, type, description, createdAt, actor)', + }, + leaveRequests: { + type: 'array', + description: 'List of leave requests (id, requestedBy, status, startDate, endDate)', + }, + leaveBalances: { type: 'array', description: 'List of leave balances (employeeId, balances)' }, + leaveTypes: { type: 'array', description: 'List of leave types (id, name, managedBy)' }, + totalCount: { type: 'number', description: 'Total number of items returned' }, + id: { type: 'string', description: 'Resource ID' }, + name: { type: 'string', description: 'Resource name' }, + workEmail: { type: 'string', description: 'Work email address' }, + company: { type: 'string', description: 'Company ID' }, + status: { type: 'string', description: 'Status of the resource' }, + users: { type: 'array', description: 'Array of user IDs in a group' }, + version: { type: 'number', description: 'Group version number' }, + address: { type: 'json', description: 'Company address (street, city, state, zip, country)' }, + email: { type: 'string', description: 'Email address' }, + phone: { type: 'string', description: 'Phone number' }, + balances: { type: 'array', description: 'Leave balance entries (leaveType, minutesRemaining)' }, + employeeId: { type: 'string', description: 'Employee ID' }, + nextCursor: { type: 'string', description: 'Cursor for fetching the next page of results' }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index a857038e02..15363a8ad5 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -145,6 +145,7 @@ import { ReductoBlock, ReductoV2Block } from '@/blocks/blocks/reducto' import { ResendBlock } from '@/blocks/blocks/resend' import { ResponseBlock } from '@/blocks/blocks/response' import { RevenueCatBlock } from '@/blocks/blocks/revenuecat' +import { RipplingBlock } from '@/blocks/blocks/rippling' import { RouterBlock, RouterV2Block } from '@/blocks/blocks/router' import { RssBlock } from '@/blocks/blocks/rss' import { S3Block } from '@/blocks/blocks/s3' @@ -367,6 +368,7 @@ export const registry: Record = { resend: ResendBlock, response: ResponseBlock, revenuecat: RevenueCatBlock, + rippling: RipplingBlock, router: RouterBlock, router_v2: RouterV2Block, rss: RssBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index a7ee06c5e8..0cf5773ca4 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -6270,6 +6270,17 @@ export function RedisIcon(props: SVGProps) { ) } +export function RipplingIcon(props: SVGProps) { + return ( + + + + ) +} + export function HexIcon(props: SVGProps) { return ( diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index be98b26b3d..640cce5c39 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -1814,6 +1814,27 @@ import { revenuecatRevokeGoogleSubscriptionTool, revenuecatUpdateSubscriberAttributesTool, } from '@/tools/revenuecat' +import { + ripplingCreateGroupTool, + ripplingGetCompanyActivityTool, + ripplingGetCompanyTool, + ripplingGetCurrentUserTool, + ripplingGetEmployeeTool, + ripplingGetLeaveBalanceTool, + ripplingListCustomFieldsTool, + ripplingListDepartmentsTool, + ripplingListEmployeesTool, + ripplingListEmployeesWithTerminatedTool, + ripplingListLeaveBalancesTool, + ripplingListLeaveRequestsTool, + ripplingListLeaveTypesTool, + ripplingListLevelsTool, + ripplingListTeamsTool, + ripplingListWorkLocationsTool, + ripplingProcessLeaveRequestTool, + ripplingPushCandidateTool, + ripplingUpdateGroupTool, +} from '@/tools/rippling' import { s3CopyObjectTool, s3DeleteObjectTool, @@ -3457,6 +3478,25 @@ export const tools: Record = { revenuecat_defer_google_subscription: revenuecatDeferGoogleSubscriptionTool, revenuecat_refund_google_subscription: revenuecatRefundGoogleSubscriptionTool, revenuecat_revoke_google_subscription: revenuecatRevokeGoogleSubscriptionTool, + rippling_create_group: ripplingCreateGroupTool, + rippling_get_company: ripplingGetCompanyTool, + rippling_get_company_activity: ripplingGetCompanyActivityTool, + rippling_get_current_user: ripplingGetCurrentUserTool, + rippling_get_employee: ripplingGetEmployeeTool, + rippling_get_leave_balance: ripplingGetLeaveBalanceTool, + rippling_list_custom_fields: ripplingListCustomFieldsTool, + rippling_list_departments: ripplingListDepartmentsTool, + rippling_list_employees: ripplingListEmployeesTool, + rippling_list_employees_with_terminated: ripplingListEmployeesWithTerminatedTool, + rippling_list_leave_balances: ripplingListLeaveBalancesTool, + rippling_list_leave_requests: ripplingListLeaveRequestsTool, + rippling_list_leave_types: ripplingListLeaveTypesTool, + rippling_list_levels: ripplingListLevelsTool, + rippling_list_teams: ripplingListTeamsTool, + rippling_list_work_locations: ripplingListWorkLocationsTool, + rippling_process_leave_request: ripplingProcessLeaveRequestTool, + rippling_push_candidate: ripplingPushCandidateTool, + rippling_update_group: ripplingUpdateGroupTool, google_drive_copy: googleDriveCopyTool, google_drive_create_folder: googleDriveCreateFolderTool, google_drive_delete: googleDriveDeleteTool, diff --git a/apps/sim/tools/rippling/create_group.ts b/apps/sim/tools/rippling/create_group.ts new file mode 100644 index 0000000000..d4987eaacf --- /dev/null +++ b/apps/sim/tools/rippling/create_group.ts @@ -0,0 +1,91 @@ +import type { RipplingCreateGroupParams, RipplingCreateGroupResponse } from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingCreateGroupTool: ToolConfig< + RipplingCreateGroupParams, + RipplingCreateGroupResponse +> = { + id: 'rippling_create_group', + name: 'Rippling Create Group', + description: 'Create a new group in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + name: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Name of the group', + }, + spokeId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Third-party app identifier', + }, + users: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'Array of user ID strings to add to the group', + }, + }, + + request: { + url: 'https://api.rippling.com/platform/api/groups', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + name: params.name, + spokeId: params.spokeId, + } + if (params.users !== undefined) { + body.users = params.users + } + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: (data.id as string) ?? '', + name: (data.name as string) ?? null, + spokeId: (data.spokeId as string) ?? null, + users: (data.users as string[]) ?? [], + version: (data.version as number) ?? null, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Group ID' }, + name: { type: 'string', description: 'Group name' }, + spokeId: { type: 'string', description: 'Third-party app identifier' }, + users: { + type: 'array', + description: 'Array of user IDs in the group', + items: { type: 'string' }, + }, + version: { type: 'number', description: 'Group version number' }, + }, +} diff --git a/apps/sim/tools/rippling/get_company.ts b/apps/sim/tools/rippling/get_company.ts new file mode 100644 index 0000000000..fe3c0973f6 --- /dev/null +++ b/apps/sim/tools/rippling/get_company.ts @@ -0,0 +1,75 @@ +import type { RipplingGetCompanyParams, RipplingGetCompanyResponse } from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingGetCompanyTool: ToolConfig< + RipplingGetCompanyParams, + RipplingGetCompanyResponse +> = { + id: 'rippling_get_company', + name: 'Rippling Get Company', + description: 'Get details for the current company in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + }, + + request: { + url: 'https://api.rippling.com/platform/api/companies/current', + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + const address = data.address ?? {} + + return { + success: true, + output: { + id: data.id ?? '', + name: data.name ?? null, + address: { + street: address.street ?? null, + city: address.city ?? null, + state: address.state ?? null, + zip: address.zip ?? null, + country: address.country ?? null, + }, + email: data.email ?? null, + phone: data.phone ?? null, + workLocations: data.workLocations ?? [], + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Company ID' }, + name: { type: 'string', description: 'Company name', optional: true }, + address: { + type: 'json', + description: 'Company address with street, city, state, zip, country', + }, + email: { type: 'string', description: 'Company email address', optional: true }, + phone: { type: 'string', description: 'Company phone number', optional: true }, + workLocations: { + type: 'array', + description: 'List of work location IDs', + items: { type: 'string' }, + }, + }, +} diff --git a/apps/sim/tools/rippling/get_company_activity.ts b/apps/sim/tools/rippling/get_company_activity.ts new file mode 100644 index 0000000000..af786d220f --- /dev/null +++ b/apps/sim/tools/rippling/get_company_activity.ts @@ -0,0 +1,125 @@ +import type { + RipplingGetCompanyActivityParams, + RipplingGetCompanyActivityResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingGetCompanyActivityTool: ToolConfig< + RipplingGetCompanyActivityParams, + RipplingGetCompanyActivityResponse +> = { + id: 'rippling_get_company_activity', + name: 'Rippling Get Company Activity', + description: 'Get activity events for the current company in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + startDate: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Start date filter in ISO format (e.g. 2024-01-01)', + }, + endDate: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'End date filter in ISO format (e.g. 2024-12-31)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of activity events to return', + }, + next: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Cursor for fetching the next page of results', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.startDate) query.set('startDate', params.startDate) + if (params.endDate) query.set('endDate', params.endDate) + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.next) query.set('next', params.next) + const qs = query.toString() + return `https://api.rippling.com/platform/api/company_activity${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + const nextCursor = Array.isArray(data) ? null : ((data.next as string) ?? null) + + const events = results.map((event: Record) => { + const actor = (event.actor as Record) ?? {} + return { + id: (event.id as string) ?? '', + type: (event.type as string) ?? null, + description: (event.description as string) ?? null, + createdAt: (event.createdAt as string) ?? null, + actor: { + id: (actor.id as string) ?? null, + name: (actor.name as string) ?? null, + }, + } + }) + + return { + success: true, + output: { + events, + totalCount: events.length, + nextCursor, + }, + } + }, + + outputs: { + events: { + type: 'array', + description: 'List of company activity events', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Event ID' }, + type: { type: 'string', description: 'Event type' }, + description: { type: 'string', description: 'Event description' }, + createdAt: { type: 'string', description: 'Event creation timestamp' }, + actor: { type: 'json', description: 'Actor who triggered the event (id, name)' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of activity events returned', + }, + nextCursor: { + type: 'string', + description: 'Cursor for fetching the next page of results', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/rippling/get_current_user.ts b/apps/sim/tools/rippling/get_current_user.ts new file mode 100644 index 0000000000..3ee6ebb14c --- /dev/null +++ b/apps/sim/tools/rippling/get_current_user.ts @@ -0,0 +1,57 @@ +import type { + RipplingGetCurrentUserParams, + RipplingGetCurrentUserResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingGetCurrentUserTool: ToolConfig< + RipplingGetCurrentUserParams, + RipplingGetCurrentUserResponse +> = { + id: 'rippling_get_current_user', + name: 'Rippling Get Current User', + description: 'Get the current authenticated user details', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + }, + + request: { + url: 'https://api.rippling.com/platform/api/me', + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: data.id ?? '', + workEmail: data.workEmail ?? null, + company: data.company ?? null, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'User ID' }, + workEmail: { type: 'string', description: 'Work email address', optional: true }, + company: { type: 'string', description: 'Company ID', optional: true }, + }, +} diff --git a/apps/sim/tools/rippling/get_employee.ts b/apps/sim/tools/rippling/get_employee.ts new file mode 100644 index 0000000000..a9e0c56911 --- /dev/null +++ b/apps/sim/tools/rippling/get_employee.ts @@ -0,0 +1,79 @@ +import type { RipplingGetEmployeeParams, RipplingGetEmployeeResponse } from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingGetEmployeeTool: ToolConfig< + RipplingGetEmployeeParams, + RipplingGetEmployeeResponse +> = { + id: 'rippling_get_employee', + name: 'Rippling Get Employee', + description: 'Get details for a specific employee by ID', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + employeeId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the employee to retrieve', + }, + }, + + request: { + url: (params) => + `https://api.rippling.com/platform/api/employees/${encodeURIComponent(params.employeeId.trim())}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const emp = await response.json() + + return { + success: true, + output: { + id: emp.id ?? '', + firstName: emp.firstName ?? null, + lastName: emp.lastName ?? null, + workEmail: emp.workEmail ?? null, + personalEmail: emp.personalEmail ?? null, + roleState: emp.roleState ?? null, + department: emp.department ?? null, + title: emp.title ?? null, + startDate: emp.startDate ?? null, + endDate: emp.endDate ?? null, + manager: emp.manager ?? null, + phone: emp.phone ?? null, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Employee ID' }, + firstName: { type: 'string', description: 'First name', optional: true }, + lastName: { type: 'string', description: 'Last name', optional: true }, + workEmail: { type: 'string', description: 'Work email address', optional: true }, + personalEmail: { type: 'string', description: 'Personal email address', optional: true }, + roleState: { type: 'string', description: 'Employment status', optional: true }, + department: { type: 'string', description: 'Department name or ID', optional: true }, + title: { type: 'string', description: 'Job title', optional: true }, + startDate: { type: 'string', description: 'Employment start date', optional: true }, + endDate: { type: 'string', description: 'Employment end date', optional: true }, + manager: { type: 'string', description: 'Manager ID or name', optional: true }, + phone: { type: 'string', description: 'Phone number', optional: true }, + }, +} diff --git a/apps/sim/tools/rippling/get_leave_balance.ts b/apps/sim/tools/rippling/get_leave_balance.ts new file mode 100644 index 0000000000..d8f8b30322 --- /dev/null +++ b/apps/sim/tools/rippling/get_leave_balance.ts @@ -0,0 +1,77 @@ +import type { + RipplingGetLeaveBalanceParams, + RipplingGetLeaveBalanceResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingGetLeaveBalanceTool: ToolConfig< + RipplingGetLeaveBalanceParams, + RipplingGetLeaveBalanceResponse +> = { + id: 'rippling_get_leave_balance', + name: 'Rippling Get Leave Balance', + description: 'Get leave balance for a specific employee by role ID', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + roleId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The employee/role ID to retrieve leave balance for', + }, + }, + + request: { + url: (params) => + `https://api.rippling.com/platform/api/leave_balances/${encodeURIComponent(params.roleId.trim())}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + employeeId: data.employeeId ?? '', + balances: (Array.isArray(data.balances) ? data.balances : []).map( + (b: Record) => ({ + leaveType: (b.leaveType as string) ?? '', + minutesRemaining: (b.minutesRemaining as number) ?? 0, + }) + ), + }, + } + }, + + outputs: { + employeeId: { type: 'string', description: 'Employee ID' }, + balances: { + type: 'array', + description: 'Leave balance entries', + items: { + type: 'json', + properties: { + leaveType: { type: 'string', description: 'Type of leave' }, + minutesRemaining: { type: 'number', description: 'Minutes of leave remaining' }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/rippling/index.ts b/apps/sim/tools/rippling/index.ts new file mode 100644 index 0000000000..69c3a7f5c3 --- /dev/null +++ b/apps/sim/tools/rippling/index.ts @@ -0,0 +1,20 @@ +export { ripplingCreateGroupTool } from '@/tools/rippling/create_group' +export { ripplingGetCompanyTool } from '@/tools/rippling/get_company' +export { ripplingGetCompanyActivityTool } from '@/tools/rippling/get_company_activity' +export { ripplingGetCurrentUserTool } from '@/tools/rippling/get_current_user' +export { ripplingGetEmployeeTool } from '@/tools/rippling/get_employee' +export { ripplingGetLeaveBalanceTool } from '@/tools/rippling/get_leave_balance' +export { ripplingListCustomFieldsTool } from '@/tools/rippling/list_custom_fields' +export { ripplingListDepartmentsTool } from '@/tools/rippling/list_departments' +export { ripplingListEmployeesTool } from '@/tools/rippling/list_employees' +export { ripplingListEmployeesWithTerminatedTool } from '@/tools/rippling/list_employees_with_terminated' +export { ripplingListLeaveBalancesTool } from '@/tools/rippling/list_leave_balances' +export { ripplingListLeaveRequestsTool } from '@/tools/rippling/list_leave_requests' +export { ripplingListLeaveTypesTool } from '@/tools/rippling/list_leave_types' +export { ripplingListLevelsTool } from '@/tools/rippling/list_levels' +export { ripplingListTeamsTool } from '@/tools/rippling/list_teams' +export { ripplingListWorkLocationsTool } from '@/tools/rippling/list_work_locations' +export { ripplingProcessLeaveRequestTool } from '@/tools/rippling/process_leave_request' +export { ripplingPushCandidateTool } from '@/tools/rippling/push_candidate' +export * from '@/tools/rippling/types' +export { ripplingUpdateGroupTool } from '@/tools/rippling/update_group' diff --git a/apps/sim/tools/rippling/list_custom_fields.ts b/apps/sim/tools/rippling/list_custom_fields.ts new file mode 100644 index 0000000000..efe986e530 --- /dev/null +++ b/apps/sim/tools/rippling/list_custom_fields.ts @@ -0,0 +1,96 @@ +import type { + RipplingListCustomFieldsParams, + RipplingListCustomFieldsResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListCustomFieldsTool: ToolConfig< + RipplingListCustomFieldsParams, + RipplingListCustomFieldsResponse +> = { + id: 'rippling_list_custom_fields', + name: 'Rippling List Custom Fields', + description: 'List all custom fields defined in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of custom fields to return', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/custom_fields${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const customFields = results.map((field: Record) => ({ + id: (field.id as string) ?? '', + type: (field.type as string) ?? null, + title: (field.title as string) ?? null, + mandatory: Boolean(field.mandatory), + })) + + return { + success: true, + output: { + customFields, + totalCount: customFields.length, + }, + } + }, + + outputs: { + customFields: { + type: 'array', + description: 'List of custom fields', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Custom field ID' }, + type: { type: 'string', description: 'Field type' }, + title: { type: 'string', description: 'Field title' }, + mandatory: { type: 'boolean', description: 'Whether the field is mandatory' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of custom fields returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_departments.ts b/apps/sim/tools/rippling/list_departments.ts new file mode 100644 index 0000000000..e41fdb7e24 --- /dev/null +++ b/apps/sim/tools/rippling/list_departments.ts @@ -0,0 +1,94 @@ +import type { + RipplingListDepartmentsParams, + RipplingListDepartmentsResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListDepartmentsTool: ToolConfig< + RipplingListDepartmentsParams, + RipplingListDepartmentsResponse +> = { + id: 'rippling_list_departments', + name: 'Rippling List Departments', + description: 'List all departments in the Rippling organization', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of departments to return', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/departments${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const departments = results.map((dept: Record) => ({ + id: (dept.id as string) ?? '', + name: (dept.name as string) ?? null, + parent: (dept.parent as string) ?? null, + })) + + return { + success: true, + output: { + departments, + totalCount: departments.length, + }, + } + }, + + outputs: { + departments: { + type: 'array', + description: 'List of departments', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Department ID' }, + name: { type: 'string', description: 'Department name' }, + parent: { type: 'string', description: 'Parent department ID' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of departments returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_employees.ts b/apps/sim/tools/rippling/list_employees.ts new file mode 100644 index 0000000000..fb1067f15d --- /dev/null +++ b/apps/sim/tools/rippling/list_employees.ts @@ -0,0 +1,112 @@ +import type { + RipplingListEmployeesParams, + RipplingListEmployeesResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListEmployeesTool: ToolConfig< + RipplingListEmployeesParams, + RipplingListEmployeesResponse +> = { + id: 'rippling_list_employees', + name: 'Rippling List Employees', + description: 'List all employees in Rippling with optional pagination', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of employees to return (default 100, max 100)', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/employees${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const employees = results.map((emp: Record) => ({ + id: (emp.id as string) ?? '', + firstName: (emp.firstName as string) ?? null, + lastName: (emp.lastName as string) ?? null, + workEmail: (emp.workEmail as string) ?? null, + personalEmail: (emp.personalEmail as string) ?? null, + roleState: (emp.roleState as string) ?? null, + department: (emp.department as string) ?? null, + title: (emp.title as string) ?? null, + startDate: (emp.startDate as string) ?? null, + endDate: (emp.endDate as string) ?? null, + manager: (emp.manager as string) ?? null, + phone: (emp.phone as string) ?? null, + })) + + return { + success: true, + output: { + employees, + totalCount: employees.length, + }, + } + }, + + outputs: { + employees: { + type: 'array', + description: 'List of employees', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Employee ID' }, + firstName: { type: 'string', description: 'First name' }, + lastName: { type: 'string', description: 'Last name' }, + workEmail: { type: 'string', description: 'Work email address' }, + personalEmail: { type: 'string', description: 'Personal email address' }, + roleState: { type: 'string', description: 'Employment status' }, + department: { type: 'string', description: 'Department name or ID' }, + title: { type: 'string', description: 'Job title' }, + startDate: { type: 'string', description: 'Employment start date' }, + endDate: { type: 'string', description: 'Employment end date' }, + manager: { type: 'string', description: 'Manager ID or name' }, + phone: { type: 'string', description: 'Phone number' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of employees returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_employees_with_terminated.ts b/apps/sim/tools/rippling/list_employees_with_terminated.ts new file mode 100644 index 0000000000..9eddcf856d --- /dev/null +++ b/apps/sim/tools/rippling/list_employees_with_terminated.ts @@ -0,0 +1,113 @@ +import type { + RipplingListEmployeesWithTerminatedParams, + RipplingListEmployeesWithTerminatedResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListEmployeesWithTerminatedTool: ToolConfig< + RipplingListEmployeesWithTerminatedParams, + RipplingListEmployeesWithTerminatedResponse +> = { + id: 'rippling_list_employees_with_terminated', + name: 'Rippling List Employees Including Terminated', + description: + 'List all employees in Rippling including terminated employees with optional pagination', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of employees to return (default 100, max 100)', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/employees/include_terminated${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const employees = results.map((emp: Record) => ({ + id: (emp.id as string) ?? '', + firstName: (emp.firstName as string) ?? null, + lastName: (emp.lastName as string) ?? null, + workEmail: (emp.workEmail as string) ?? null, + personalEmail: (emp.personalEmail as string) ?? null, + roleState: (emp.roleState as string) ?? null, + department: (emp.department as string) ?? null, + title: (emp.title as string) ?? null, + startDate: (emp.startDate as string) ?? null, + endDate: (emp.endDate as string) ?? null, + manager: (emp.manager as string) ?? null, + phone: (emp.phone as string) ?? null, + })) + + return { + success: true, + output: { + employees, + totalCount: employees.length, + }, + } + }, + + outputs: { + employees: { + type: 'array', + description: 'List of employees including terminated', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Employee ID' }, + firstName: { type: 'string', description: 'First name' }, + lastName: { type: 'string', description: 'Last name' }, + workEmail: { type: 'string', description: 'Work email address' }, + personalEmail: { type: 'string', description: 'Personal email address' }, + roleState: { type: 'string', description: 'Employment status' }, + department: { type: 'string', description: 'Department name or ID' }, + title: { type: 'string', description: 'Job title' }, + startDate: { type: 'string', description: 'Employment start date' }, + endDate: { type: 'string', description: 'Employment end date' }, + manager: { type: 'string', description: 'Manager ID or name' }, + phone: { type: 'string', description: 'Phone number' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of employees returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_leave_balances.ts b/apps/sim/tools/rippling/list_leave_balances.ts new file mode 100644 index 0000000000..a7509679cc --- /dev/null +++ b/apps/sim/tools/rippling/list_leave_balances.ts @@ -0,0 +1,107 @@ +import type { + RipplingListLeaveBalancesParams, + RipplingListLeaveBalancesResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListLeaveBalancesTool: ToolConfig< + RipplingListLeaveBalancesParams, + RipplingListLeaveBalancesResponse +> = { + id: 'rippling_list_leave_balances', + name: 'Rippling List Leave Balances', + description: 'List leave balances for all employees in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of leave balances to return', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/leave_balances${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const leaveBalances = results.map((bal: Record) => ({ + employeeId: (bal.employeeId as string) ?? '', + balances: (Array.isArray(bal.balances) ? bal.balances : []).map( + (b: Record) => ({ + leaveType: (b.leaveType as string) ?? '', + minutesRemaining: (b.minutesRemaining as number) ?? 0, + }) + ), + })) + + return { + success: true, + output: { + leaveBalances, + totalCount: leaveBalances.length, + }, + } + }, + + outputs: { + leaveBalances: { + type: 'array', + description: 'List of employee leave balances', + items: { + type: 'json', + properties: { + employeeId: { type: 'string', description: 'Employee ID' }, + balances: { + type: 'array', + description: 'Leave balance entries', + items: { + type: 'json', + properties: { + leaveType: { type: 'string', description: 'Type of leave' }, + minutesRemaining: { type: 'number', description: 'Minutes of leave remaining' }, + }, + }, + }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of leave balances returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_leave_requests.ts b/apps/sim/tools/rippling/list_leave_requests.ts new file mode 100644 index 0000000000..2f99d267d2 --- /dev/null +++ b/apps/sim/tools/rippling/list_leave_requests.ts @@ -0,0 +1,111 @@ +import type { + RipplingListLeaveRequestsParams, + RipplingListLeaveRequestsResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListLeaveRequestsTool: ToolConfig< + RipplingListLeaveRequestsParams, + RipplingListLeaveRequestsResponse +> = { + id: 'rippling_list_leave_requests', + name: 'Rippling List Leave Requests', + description: 'List leave requests in Rippling with optional filtering by date range and status', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + startDate: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter by start date (ISO date string)', + }, + endDate: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter by end date (ISO date string)', + }, + status: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter by status (e.g. pending, approved, declined)', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.startDate) query.set('startDate', params.startDate) + if (params.endDate) query.set('endDate', params.endDate) + if (params.status) query.set('status', params.status) + const qs = query.toString() + return `https://api.rippling.com/platform/api/leave_requests${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const leaveRequests = results.map((req: Record) => ({ + id: (req.id as string) ?? '', + requestedBy: (req.requestedBy as string) ?? '', + status: (req.status as string) ?? '', + startDate: (req.startDate as string) ?? '', + endDate: (req.endDate as string) ?? '', + reason: (req.reason as string) ?? null, + leaveType: (req.leaveType as string) ?? null, + createdAt: (req.createdAt as string) ?? null, + })) + + return { + success: true, + output: { + leaveRequests, + totalCount: leaveRequests.length, + }, + } + }, + + outputs: { + leaveRequests: { + type: 'array', + description: 'List of leave requests', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Leave request ID' }, + requestedBy: { type: 'string', description: 'Employee ID who requested leave' }, + status: { type: 'string', description: 'Request status (pending/approved/declined)' }, + startDate: { type: 'string', description: 'Leave start date' }, + endDate: { type: 'string', description: 'Leave end date' }, + reason: { type: 'string', description: 'Reason for leave' }, + leaveType: { type: 'string', description: 'Type of leave' }, + createdAt: { type: 'string', description: 'When the request was created' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of leave requests returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_leave_types.ts b/apps/sim/tools/rippling/list_leave_types.ts new file mode 100644 index 0000000000..3c44c56934 --- /dev/null +++ b/apps/sim/tools/rippling/list_leave_types.ts @@ -0,0 +1,87 @@ +import type { + RipplingListLeaveTypesParams, + RipplingListLeaveTypesResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListLeaveTypesTool: ToolConfig< + RipplingListLeaveTypesParams, + RipplingListLeaveTypesResponse +> = { + id: 'rippling_list_leave_types', + name: 'Rippling List Leave Types', + description: 'List company leave types configured in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + managedBy: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter leave types by manager', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.managedBy) query.set('managedBy', params.managedBy) + const qs = query.toString() + return `https://api.rippling.com/platform/api/company_leave_types${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const leaveTypes = results.map((lt: Record) => ({ + id: (lt.id as string) ?? '', + name: (lt.name as string) ?? '', + managedBy: (lt.managedBy as string) ?? null, + })) + + return { + success: true, + output: { + leaveTypes, + totalCount: leaveTypes.length, + }, + } + }, + + outputs: { + leaveTypes: { + type: 'array', + description: 'List of company leave types', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Leave type ID' }, + name: { type: 'string', description: 'Leave type name' }, + managedBy: { type: 'string', description: 'Manager of this leave type' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of leave types returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_levels.ts b/apps/sim/tools/rippling/list_levels.ts new file mode 100644 index 0000000000..0739b236aa --- /dev/null +++ b/apps/sim/tools/rippling/list_levels.ts @@ -0,0 +1,91 @@ +import type { RipplingListLevelsParams, RipplingListLevelsResponse } from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListLevelsTool: ToolConfig< + RipplingListLevelsParams, + RipplingListLevelsResponse +> = { + id: 'rippling_list_levels', + name: 'Rippling List Levels', + description: 'List all position levels in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of levels to return', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/levels${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const levels = results.map((level: Record) => ({ + id: (level.id as string) ?? '', + name: (level.name as string) ?? null, + parent: (level.parent as string) ?? null, + })) + + return { + success: true, + output: { + levels, + totalCount: levels.length, + }, + } + }, + + outputs: { + levels: { + type: 'array', + description: 'List of position levels', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Level ID' }, + name: { type: 'string', description: 'Level name' }, + parent: { type: 'string', description: 'Parent level ID' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of levels returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/list_teams.ts b/apps/sim/tools/rippling/list_teams.ts new file mode 100644 index 0000000000..f36891b579 --- /dev/null +++ b/apps/sim/tools/rippling/list_teams.ts @@ -0,0 +1,89 @@ +import type { RipplingListTeamsParams, RipplingListTeamsResponse } from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListTeamsTool: ToolConfig = + { + id: 'rippling_list_teams', + name: 'Rippling List Teams', + description: 'List all teams in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of teams to return', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/teams${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const teams = results.map((team: Record) => ({ + id: (team.id as string) ?? '', + name: (team.name as string) ?? null, + parent: (team.parent as string) ?? null, + })) + + return { + success: true, + output: { + teams, + totalCount: teams.length, + }, + } + }, + + outputs: { + teams: { + type: 'array', + description: 'List of teams', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Team ID' }, + name: { type: 'string', description: 'Team name' }, + parent: { type: 'string', description: 'Parent team ID' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of teams returned', + }, + }, + } diff --git a/apps/sim/tools/rippling/list_work_locations.ts b/apps/sim/tools/rippling/list_work_locations.ts new file mode 100644 index 0000000000..cfd7ad2912 --- /dev/null +++ b/apps/sim/tools/rippling/list_work_locations.ts @@ -0,0 +1,102 @@ +import type { + RipplingListWorkLocationsParams, + RipplingListWorkLocationsResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingListWorkLocationsTool: ToolConfig< + RipplingListWorkLocationsParams, + RipplingListWorkLocationsResponse +> = { + id: 'rippling_list_work_locations', + name: 'Rippling List Work Locations', + description: 'List all work locations in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of work locations to return', + }, + offset: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Offset for pagination', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams() + if (params.limit != null) query.set('limit', String(params.limit)) + if (params.offset != null) query.set('offset', String(params.offset)) + const qs = query.toString() + return `https://api.rippling.com/platform/api/work_locations${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : (data.results ?? []) + + const workLocations = results.map((loc: Record) => ({ + id: (loc.id as string) ?? '', + nickname: (loc.nickname as string) ?? null, + street: (loc.street as string) ?? null, + city: (loc.city as string) ?? null, + state: (loc.state as string) ?? null, + zip: (loc.zip as string) ?? null, + country: (loc.country as string) ?? null, + })) + + return { + success: true, + output: { + workLocations, + totalCount: workLocations.length, + }, + } + }, + + outputs: { + workLocations: { + type: 'array', + description: 'List of work locations', + items: { + type: 'json', + properties: { + id: { type: 'string', description: 'Work location ID' }, + nickname: { type: 'string', description: 'Location nickname' }, + street: { type: 'string', description: 'Street address' }, + city: { type: 'string', description: 'City' }, + state: { type: 'string', description: 'State or province' }, + zip: { type: 'string', description: 'ZIP or postal code' }, + country: { type: 'string', description: 'Country' }, + }, + }, + }, + totalCount: { + type: 'number', + description: 'Total number of work locations returned', + }, + }, +} diff --git a/apps/sim/tools/rippling/process_leave_request.ts b/apps/sim/tools/rippling/process_leave_request.ts new file mode 100644 index 0000000000..eefd0f757b --- /dev/null +++ b/apps/sim/tools/rippling/process_leave_request.ts @@ -0,0 +1,74 @@ +import type { + RipplingProcessLeaveRequestParams, + RipplingProcessLeaveRequestResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingProcessLeaveRequestTool: ToolConfig< + RipplingProcessLeaveRequestParams, + RipplingProcessLeaveRequestResponse +> = { + id: 'rippling_process_leave_request', + name: 'Rippling Process Leave Request', + description: 'Approve or decline a leave request in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + leaveRequestId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the leave request to process', + }, + action: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Action to take on the leave request (approve or decline)', + }, + }, + + request: { + url: (params) => + `https://api.rippling.com/platform/api/leave_requests/${encodeURIComponent(params.leaveRequestId.trim())}/process?action=${encodeURIComponent(params.action.trim())}`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: data.id ?? '', + status: data.status ?? '', + requestedBy: data.requestedBy ?? '', + startDate: data.startDate ?? '', + endDate: data.endDate ?? '', + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Leave request ID' }, + status: { type: 'string', description: 'Updated status of the leave request' }, + requestedBy: { type: 'string', description: 'Employee ID who requested leave' }, + startDate: { type: 'string', description: 'Leave start date' }, + endDate: { type: 'string', description: 'Leave end date' }, + }, +} diff --git a/apps/sim/tools/rippling/push_candidate.ts b/apps/sim/tools/rippling/push_candidate.ts new file mode 100644 index 0000000000..c98480ba50 --- /dev/null +++ b/apps/sim/tools/rippling/push_candidate.ts @@ -0,0 +1,124 @@ +import type { + RipplingPushCandidateParams, + RipplingPushCandidateResponse, +} from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingPushCandidateTool: ToolConfig< + RipplingPushCandidateParams, + RipplingPushCandidateResponse +> = { + id: 'rippling_push_candidate', + name: 'Rippling Push Candidate', + description: 'Push a candidate to onboarding in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + firstName: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Candidate first name', + }, + lastName: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Candidate last name', + }, + email: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Candidate email address', + }, + phone: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Candidate phone number', + }, + jobTitle: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Job title for the candidate', + }, + department: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Department for the candidate', + }, + startDate: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Start date in ISO 8601 format (e.g., 2025-01-15)', + }, + }, + + request: { + url: 'https://api.rippling.com/platform/api/ats_candidates/push_candidate', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + firstName: params.firstName, + lastName: params.lastName, + email: params.email, + } + if (params.phone !== undefined) { + body.phone = params.phone + } + if (params.jobTitle !== undefined) { + body.jobTitle = params.jobTitle + } + if (params.department !== undefined) { + body.department = params.department + } + if (params.startDate !== undefined) { + body.startDate = params.startDate + } + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: (data.id as string) ?? '', + firstName: (data.firstName as string) ?? null, + lastName: (data.lastName as string) ?? null, + email: (data.email as string) ?? null, + status: (data.status as string) ?? null, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Candidate ID' }, + firstName: { type: 'string', description: 'Candidate first name' }, + lastName: { type: 'string', description: 'Candidate last name' }, + email: { type: 'string', description: 'Candidate email address' }, + status: { type: 'string', description: 'Candidate onboarding status', optional: true }, + }, +} diff --git a/apps/sim/tools/rippling/types.ts b/apps/sim/tools/rippling/types.ts new file mode 100644 index 0000000000..7c7211de6e --- /dev/null +++ b/apps/sim/tools/rippling/types.ts @@ -0,0 +1,362 @@ +import type { ToolResponse } from '@/tools/types' + +export interface RipplingListEmployeesParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingGetEmployeeParams { + apiKey: string + employeeId: string +} + +export interface RipplingListDepartmentsParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingGetCurrentUserParams { + apiKey: string +} + +export interface RipplingEmployee { + id: string + firstName: string | null + lastName: string | null + workEmail: string | null + personalEmail: string | null + roleState: string | null + department: string | null + title: string | null + startDate: string | null + endDate: string | null + manager: string | null + phone: string | null +} + +export interface RipplingDepartment { + id: string + name: string | null + parent: string | null +} + +export interface RipplingListEmployeesResponse extends ToolResponse { + output: { + employees: RipplingEmployee[] + totalCount: number + } +} + +export interface RipplingGetEmployeeResponse extends ToolResponse { + output: RipplingEmployee +} + +export interface RipplingListDepartmentsResponse extends ToolResponse { + output: { + departments: RipplingDepartment[] + totalCount: number + } +} + +export interface RipplingGetCurrentUserResponse extends ToolResponse { + output: { + id: string + workEmail: string | null + company: string | null + } +} + +export interface RipplingGetCompanyParams { + apiKey: string +} + +export interface RipplingCompanyAddress { + street: string | null + city: string | null + state: string | null + zip: string | null + country: string | null +} + +export interface RipplingGetCompanyResponse extends ToolResponse { + output: { + id: string + name: string | null + address: RipplingCompanyAddress + email: string | null + phone: string | null + workLocations: string[] + } +} + +export interface RipplingListCustomFieldsParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingCustomField { + id: string + type: string | null + title: string | null + mandatory: boolean +} + +export interface RipplingListCustomFieldsResponse extends ToolResponse { + output: { + customFields: RipplingCustomField[] + totalCount: number + } +} + +export interface RipplingListLevelsParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingLevel { + id: string + name: string | null + parent: string | null +} + +export interface RipplingListLevelsResponse extends ToolResponse { + output: { + levels: RipplingLevel[] + totalCount: number + } +} + +export interface RipplingListTeamsParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingTeam { + id: string + name: string | null + parent: string | null +} + +export interface RipplingListTeamsResponse extends ToolResponse { + output: { + teams: RipplingTeam[] + totalCount: number + } +} + +export interface RipplingListWorkLocationsParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingWorkLocation { + id: string + nickname: string | null + street: string | null + city: string | null + state: string | null + zip: string | null + country: string | null +} + +export interface RipplingListWorkLocationsResponse extends ToolResponse { + output: { + workLocations: RipplingWorkLocation[] + totalCount: number + } +} + +export interface RipplingGetCompanyActivityParams { + apiKey: string + startDate?: string + endDate?: string + limit?: number + next?: string +} + +export interface RipplingActivityActor { + id: string | null + name: string | null +} + +export interface RipplingActivityEvent { + id: string + type: string | null + description: string | null + createdAt: string | null + actor: RipplingActivityActor +} + +export interface RipplingGetCompanyActivityResponse extends ToolResponse { + output: { + events: RipplingActivityEvent[] + totalCount: number + nextCursor: string | null + } +} + +export interface RipplingListEmployeesWithTerminatedParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingListEmployeesWithTerminatedResponse extends ToolResponse { + output: { + employees: RipplingEmployee[] + totalCount: number + } +} + +export interface RipplingCreateGroupParams { + apiKey: string + name: string + spokeId: string + users?: string[] +} + +export interface RipplingGroup { + id: string + name: string | null + spokeId: string | null + users: string[] + version: number | null +} + +export interface RipplingCreateGroupResponse extends ToolResponse { + output: RipplingGroup +} + +export interface RipplingUpdateGroupParams { + apiKey: string + groupId: string + name?: string + spokeId?: string + users?: string[] + version?: number +} + +export interface RipplingUpdateGroupResponse extends ToolResponse { + output: RipplingGroup +} + +export interface RipplingPushCandidateParams { + apiKey: string + firstName: string + lastName: string + email: string + phone?: string + jobTitle?: string + department?: string + startDate?: string +} + +export interface RipplingPushCandidateResponse extends ToolResponse { + output: { + id: string + firstName: string | null + lastName: string | null + email: string | null + status: string | null + } +} + +export interface RipplingListLeaveRequestsParams { + apiKey: string + startDate?: string + endDate?: string + status?: string +} + +export interface RipplingLeaveRequest { + id: string + requestedBy: string + status: string + startDate: string + endDate: string + reason: string | null + leaveType: string | null + createdAt: string | null +} + +export interface RipplingListLeaveRequestsResponse extends ToolResponse { + output: { + leaveRequests: RipplingLeaveRequest[] + totalCount: number + } +} + +export interface RipplingProcessLeaveRequestParams { + apiKey: string + leaveRequestId: string + action: string +} + +export interface RipplingProcessLeaveRequestResponse extends ToolResponse { + output: { + id: string + status: string + requestedBy: string + startDate: string + endDate: string + } +} + +export interface RipplingListLeaveBalancesParams { + apiKey: string + limit?: number + offset?: number +} + +export interface RipplingLeaveBalanceEntry { + leaveType: string + minutesRemaining: number +} + +export interface RipplingLeaveBalance { + employeeId: string + balances: RipplingLeaveBalanceEntry[] +} + +export interface RipplingListLeaveBalancesResponse extends ToolResponse { + output: { + leaveBalances: RipplingLeaveBalance[] + totalCount: number + } +} + +export interface RipplingGetLeaveBalanceParams { + apiKey: string + roleId: string +} + +export interface RipplingGetLeaveBalanceResponse extends ToolResponse { + output: { + employeeId: string + balances: RipplingLeaveBalanceEntry[] + } +} + +export interface RipplingListLeaveTypesParams { + apiKey: string + managedBy?: string +} + +export interface RipplingLeaveType { + id: string + name: string + managedBy: string | null +} + +export interface RipplingListLeaveTypesResponse extends ToolResponse { + output: { + leaveTypes: RipplingLeaveType[] + totalCount: number + } +} diff --git a/apps/sim/tools/rippling/update_group.ts b/apps/sim/tools/rippling/update_group.ts new file mode 100644 index 0000000000..cd31572f79 --- /dev/null +++ b/apps/sim/tools/rippling/update_group.ts @@ -0,0 +1,110 @@ +import type { RipplingUpdateGroupParams, RipplingUpdateGroupResponse } from '@/tools/rippling/types' +import type { ToolConfig } from '@/tools/types' + +export const ripplingUpdateGroupTool: ToolConfig< + RipplingUpdateGroupParams, + RipplingUpdateGroupResponse +> = { + id: 'rippling_update_group', + name: 'Rippling Update Group', + description: 'Update an existing group in Rippling', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Rippling API key', + }, + groupId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the group to update', + }, + name: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'New name for the group', + }, + spokeId: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Third-party app identifier', + }, + users: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'Array of user ID strings to set for the group', + }, + version: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Group version number for optimistic concurrency', + }, + }, + + request: { + url: (params) => + `https://api.rippling.com/platform/api/groups/${encodeURIComponent(params.groupId.trim())}`, + method: 'PUT', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = {} + if (params.name !== undefined) { + body.name = params.name + } + if (params.spokeId !== undefined) { + body.spokeId = params.spokeId + } + if (params.users !== undefined) { + body.users = params.users + } + if (params.version !== undefined) { + body.version = params.version + } + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Rippling API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: (data.id as string) ?? '', + name: (data.name as string) ?? null, + spokeId: (data.spokeId as string) ?? null, + users: (data.users as string[]) ?? [], + version: (data.version as number) ?? null, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Group ID' }, + name: { type: 'string', description: 'Group name' }, + spokeId: { type: 'string', description: 'Third-party app identifier' }, + users: { + type: 'array', + description: 'Array of user IDs in the group', + items: { type: 'string' }, + }, + version: { type: 'number', description: 'Group version number' }, + }, +} From 2beee21529cd7ce795a61dda0fe4560141879611 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 25 Mar 2026 10:56:40 -0700 Subject: [PATCH 2/6] fix(rippling): address PR review feedback - Fix lint:check import ordering in icon-mapping.ts - Build clean params object instead of spreading all UI fields to API - Add try/catch around JSON.parse for users field - Use != null guard for limit/offset to not drop 0 values - Add missing tags to block config and integrations.json --- .../integrations/data/icon-mapping.ts | 14 +- .../integrations/data/integrations.json | 912 ++++-------------- apps/sim/blocks/blocks/rippling.ts | 59 +- 3 files changed, 225 insertions(+), 760 deletions(-) diff --git a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts index fa2c8b75a1..7580b713c5 100644 --- a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts +++ b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts @@ -33,8 +33,8 @@ import { DatadogIcon, DevinIcon, DiscordIcon, - DocuSignIcon, DocumentIcon, + DocuSignIcon, DropboxIcon, DsPyIcon, DubIcon, @@ -50,8 +50,8 @@ import { FirecrawlIcon, FirefliesIcon, GammaIcon, - GitLabIcon, GithubIcon, + GitLabIcon, GmailIcon, GongIcon, GoogleAdsIcon, @@ -95,9 +95,9 @@ import { LinkupIcon, LoopsIcon, LumaIcon, - MailServerIcon, MailchimpIcon, MailgunIcon, + MailServerIcon, Mem0Icon, MicrosoftDataverseIcon, MicrosoftExcelIcon, @@ -135,8 +135,6 @@ import { RevenueCatIcon, RipplingIcon, S3Icon, - SQSIcon, - STTIcon, SalesforceIcon, SearchIcon, SendgridIcon, @@ -148,17 +146,19 @@ import { SimilarwebIcon, SlackIcon, SmtpIcon, + SQSIcon, SshIcon, + STTIcon, StagehandIcon, StripeIcon, SupabaseIcon, - TTSIcon, TavilyIcon, TelegramIcon, TextractIcon, TinybirdIcon, TranslateIcon, TrelloIcon, + TTSIcon, TwilioIcon, TypeformIcon, UpstashIcon, @@ -170,11 +170,11 @@ import { WikipediaIcon, WordpressIcon, WorkdayIcon, + xIcon, YouTubeIcon, ZendeskIcon, ZepIcon, ZoomIcon, - xIcon, } from '@/components/icons' type IconComponent = ComponentType> diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index a5a69b1588..2b3f9e19a1 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -52,10 +52,7 @@ "authType": "api-key", "category": "tools", "integrationType": "security", - "tags": [ - "secrets-management", - "identity" - ] + "tags": ["secrets-management", "identity"] }, { "type": "a2a", @@ -106,10 +103,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "agentic", - "automation" - ] + "tags": ["agentic", "automation"] }, { "type": "ahrefs", @@ -160,11 +154,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "seo", - "marketing", - "data-analytics" - ] + "tags": ["seo", "marketing", "data-analytics"] }, { "type": "airtable", @@ -221,10 +211,7 @@ "authType": "oauth", "category": "tools", "integrationType": "databases", - "tags": [ - "spreadsheet", - "automation" - ] + "tags": ["spreadsheet", "automation"] }, { "type": "airweave", @@ -242,10 +229,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "vector-search", - "knowledge-base" - ] + "tags": ["vector-search", "knowledge-base"] }, { "type": "algolia", @@ -324,10 +308,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "vector-search", - "knowledge-base" - ] + "tags": ["vector-search", "knowledge-base"] }, { "type": "dynamodb", @@ -374,10 +355,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "cloud", - "data-warehouse" - ] + "tags": ["cloud", "data-warehouse"] }, { "type": "rds", @@ -420,10 +398,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "cloud", - "data-warehouse" - ] + "tags": ["cloud", "data-warehouse"] }, { "type": "sqs", @@ -446,11 +421,7 @@ "authType": "none", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "cloud", - "messaging", - "automation" - ] + "tags": ["cloud", "messaging", "automation"] }, { "type": "amplitude", @@ -513,10 +484,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "data-analytics", - "marketing" - ] + "tags": ["data-analytics", "marketing"] }, { "type": "apify", @@ -543,11 +511,7 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": [ - "web-scraping", - "automation", - "data-analytics" - ] + "tags": ["web-scraping", "automation", "data-analytics"] }, { "type": "apollo", @@ -666,10 +630,7 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": [ - "enrichment", - "sales-engagement" - ] + "tags": ["enrichment", "sales-engagement"] }, { "type": "arxiv", @@ -700,10 +661,7 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": [ - "document-processing", - "knowledge-base" - ] + "tags": ["document-processing", "knowledge-base"] }, { "type": "asana", @@ -746,11 +704,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "project-management", - "ticketing", - "automation" - ] + "tags": ["project-management", "ticketing", "automation"] }, { "type": "ashby", @@ -912,9 +866,7 @@ "authType": "api-key", "category": "tools", "integrationType": "hr", - "tags": [ - "hiring" - ] + "tags": ["hiring"] }, { "type": "attio", @@ -952,7 +904,7 @@ }, { "name": "Assert Record (Upsert)", - "description": "Upsert a record in Attio — creates it if no match is found, updates it if a match exists" + "description": "Upsert a record in Attio \u2014 creates it if no match is found, updates it if a match exists" }, { "name": "List Notes", @@ -1184,10 +1136,7 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": [ - "sales-engagement", - "enrichment" - ] + "tags": ["sales-engagement", "enrichment"] }, { "type": "textract_v2", @@ -1205,11 +1154,7 @@ "authType": "none", "category": "tools", "integrationType": "ai", - "tags": [ - "document-processing", - "ocr", - "cloud" - ] + "tags": ["document-processing", "ocr", "cloud"] }, { "type": "microsoft_ad", @@ -1280,10 +1225,7 @@ "authType": "oauth", "category": "tools", "integrationType": "security", - "tags": [ - "identity", - "microsoft-365" - ] + "tags": ["identity", "microsoft-365"] }, { "type": "box", @@ -1362,11 +1304,7 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": [ - "cloud", - "content-management", - "e-signatures" - ] + "tags": ["cloud", "content-management", "e-signatures"] }, { "type": "brandfetch", @@ -1393,10 +1331,7 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": [ - "enrichment", - "marketing" - ] + "tags": ["enrichment", "marketing"] }, { "type": "browser_use", @@ -1414,11 +1349,7 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": [ - "web-scraping", - "automation", - "agentic" - ] + "tags": ["web-scraping", "automation", "agentic"] }, { "type": "calcom", @@ -1559,11 +1490,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "scheduling", - "calendar", - "meeting" - ] + "tags": ["scheduling", "calendar", "meeting"] }, { "type": "calendly", @@ -1631,11 +1558,7 @@ "authType": "api-key", "category": "tools", "integrationType": "productivity", - "tags": [ - "scheduling", - "calendar", - "meeting" - ] + "tags": ["scheduling", "calendar", "meeting"] }, { "type": "circleback", @@ -1669,11 +1592,7 @@ "authType": "none", "category": "triggers", "integrationType": "ai", - "tags": [ - "meeting", - "note-taking", - "automation" - ] + "tags": ["meeting", "note-taking", "automation"] }, { "type": "clay", @@ -1691,11 +1610,7 @@ "authType": "none", "category": "tools", "integrationType": "sales-intelligence", - "tags": [ - "enrichment", - "sales-engagement", - "data-analytics" - ] + "tags": ["enrichment", "sales-engagement", "data-analytics"] }, { "type": "clerk", @@ -1758,10 +1673,7 @@ "authType": "none", "category": "tools", "integrationType": "security", - "tags": [ - "identity", - "automation" - ] + "tags": ["identity", "automation"] }, { "type": "cloudflare", @@ -1832,10 +1744,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "cloud", - "monitoring" - ] + "tags": ["cloud", "monitoring"] }, { "type": "confluence_v2", @@ -2119,11 +2028,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "knowledge-base", - "content-management", - "note-taking" - ] + "tags": ["knowledge-base", "content-management", "note-taking"] }, { "type": "cursor_v2", @@ -2170,10 +2075,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "agentic", - "automation" - ] + "tags": ["agentic", "automation"] }, { "type": "databricks", @@ -2224,11 +2126,7 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": [ - "data-warehouse", - "data-analytics", - "cloud" - ] + "tags": ["data-warehouse", "data-analytics", "cloud"] }, { "type": "datadog", @@ -2295,11 +2193,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "monitoring", - "incident-management", - "error-tracking" - ] + "tags": ["monitoring", "incident-management", "error-tracking"] }, { "type": "devin", @@ -2334,10 +2228,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "agentic", - "automation" - ] + "tags": ["agentic", "automation"] }, { "type": "discord", @@ -2496,11 +2387,7 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "webhooks", - "automation" - ] + "tags": ["messaging", "webhooks", "automation"] }, { "type": "docusign", @@ -2551,10 +2438,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "e-signatures", - "document-processing" - ] + "tags": ["e-signatures", "document-processing"] }, { "type": "dropbox", @@ -2613,17 +2497,14 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": [ - "cloud", - "document-processing" - ] + "tags": ["cloud", "document-processing"] }, { "type": "dspy", "slug": "dspy", "name": "DSPy", "description": "Run predictions using self-hosted DSPy programs", - "longDescription": "Integrate with your self-hosted DSPy programs for LLM-powered predictions. Supports Predict, Chain of Thought, and ReAct agents. DSPy is the framework for programming—not prompting—language models.", + "longDescription": "Integrate with your self-hosted DSPy programs for LLM-powered predictions. Supports Predict, Chain of Thought, and ReAct agents. DSPy is the framework for programming\u2014not prompting\u2014language models.", "bgColor": "#E0E0E0", "iconName": "DsPyIcon", "docsUrl": "https://docs.sim.ai/tools/dspy", @@ -2647,11 +2528,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "agentic", - "automation" - ] + "tags": ["llm", "agentic", "automation"] }, { "type": "dub", @@ -2698,11 +2575,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "link-management", - "marketing", - "data-analytics" - ] + "tags": ["link-management", "marketing", "data-analytics"] }, { "type": "duckduckgo", @@ -2720,10 +2593,7 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "seo" - ] + "tags": ["web-scraping", "seo"] }, { "type": "elasticsearch", @@ -2794,10 +2664,7 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": [ - "vector-search", - "data-analytics" - ] + "tags": ["vector-search", "data-analytics"] }, { "type": "elevenlabs", @@ -2815,9 +2682,7 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": [ - "text-to-speech" - ] + "tags": ["text-to-speech"] }, { "type": "openai", @@ -2835,10 +2700,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "vector-search" - ] + "tags": ["llm", "vector-search"] }, { "type": "enrich", @@ -2973,10 +2835,7 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": [ - "enrichment", - "data-analytics" - ] + "tags": ["enrichment", "data-analytics"] }, { "type": "evernote", @@ -3039,10 +2898,7 @@ "authType": "api-key", "category": "tools", "integrationType": "documents", - "tags": [ - "note-taking", - "knowledge-base" - ] + "tags": ["note-taking", "knowledge-base"] }, { "type": "exa", @@ -3081,10 +2937,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "enrichment" - ] + "tags": ["web-scraping", "enrichment"] }, { "type": "fathom", @@ -3134,10 +2987,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "meeting", - "note-taking" - ] + "tags": ["meeting", "note-taking"] }, { "type": "file_v3", @@ -3155,9 +3005,7 @@ "authType": "none", "category": "tools", "integrationType": "file-storage", - "tags": [ - "document-processing" - ] + "tags": ["document-processing"] }, { "type": "firecrawl", @@ -3200,10 +3048,7 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": [ - "web-scraping", - "automation" - ] + "tags": ["web-scraping", "automation"] }, { "type": "fireflies_v2", @@ -3268,11 +3113,7 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": [ - "meeting", - "speech-to-text", - "note-taking" - ] + "tags": ["meeting", "speech-to-text", "note-taking"] }, { "type": "gamma", @@ -3311,10 +3152,7 @@ "authType": "api-key", "category": "tools", "integrationType": "design", - "tags": [ - "document-processing", - "content-management" - ] + "tags": ["document-processing", "content-management"] }, { "type": "github_v2", @@ -3721,10 +3559,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "version-control", - "ci-cd" - ] + "tags": ["version-control", "ci-cd"] }, { "type": "gitlab", @@ -3819,10 +3654,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "version-control", - "ci-cd" - ] + "tags": ["version-control", "ci-cd"] }, { "type": "gmail_v2", @@ -3889,10 +3721,7 @@ "authType": "oauth", "category": "tools", "integrationType": "email", - "tags": [ - "google-workspace", - "messaging" - ] + "tags": ["google-workspace", "messaging"] }, { "type": "gong", @@ -3983,11 +3812,7 @@ "authType": "none", "category": "tools", "integrationType": "sales-intelligence", - "tags": [ - "meeting", - "sales-engagement", - "speech-to-text" - ] + "tags": ["meeting", "sales-engagement", "speech-to-text"] }, { "type": "google_ads", @@ -4030,11 +3855,7 @@ "authType": "oauth", "category": "tools", "integrationType": "analytics", - "tags": [ - "marketing", - "google-workspace", - "data-analytics" - ] + "tags": ["marketing", "google-workspace", "data-analytics"] }, { "type": "google_bigquery", @@ -4073,11 +3894,7 @@ "authType": "oauth", "category": "tools", "integrationType": "databases", - "tags": [ - "data-warehouse", - "google-workspace", - "data-analytics" - ] + "tags": ["data-warehouse", "google-workspace", "data-analytics"] }, { "type": "google_books", @@ -4104,11 +3921,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "google-workspace", - "knowledge-base", - "content-management" - ] + "tags": ["google-workspace", "knowledge-base", "content-management"] }, { "type": "google_calendar_v2", @@ -4167,11 +3980,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "calendar", - "scheduling", - "google-workspace" - ] + "tags": ["calendar", "scheduling", "google-workspace"] }, { "type": "google_contacts", @@ -4214,11 +4023,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "google-workspace", - "customer-support", - "enrichment" - ] + "tags": ["google-workspace", "customer-support", "enrichment"] }, { "type": "google_docs", @@ -4249,11 +4054,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "google-workspace", - "document-processing", - "content-management" - ] + "tags": ["google-workspace", "document-processing", "content-management"] }, { "type": "google_drive", @@ -4328,11 +4129,7 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": [ - "cloud", - "google-workspace", - "document-processing" - ] + "tags": ["cloud", "google-workspace", "document-processing"] }, { "type": "google_forms", @@ -4393,11 +4190,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "google-workspace", - "forms", - "data-analytics" - ] + "tags": ["google-workspace", "forms", "data-analytics"] }, { "type": "google_groups", @@ -4480,11 +4273,7 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": [ - "google-workspace", - "messaging", - "identity" - ] + "tags": ["google-workspace", "messaging", "identity"] }, { "type": "google_maps", @@ -4555,10 +4344,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "google-workspace", - "enrichment" - ] + "tags": ["google-workspace", "enrichment"] }, { "type": "google_meet", @@ -4601,11 +4387,7 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": [ - "meeting", - "google-workspace", - "scheduling" - ] + "tags": ["meeting", "google-workspace", "scheduling"] }, { "type": "google_pagespeed", @@ -4623,11 +4405,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "google-workspace", - "seo", - "monitoring" - ] + "tags": ["google-workspace", "seo", "monitoring"] }, { "type": "google_search", @@ -4645,11 +4423,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "google-workspace", - "web-scraping", - "seo" - ] + "tags": ["google-workspace", "web-scraping", "seo"] }, { "type": "google_sheets_v2", @@ -4712,11 +4486,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "spreadsheet", - "google-workspace", - "data-analytics" - ] + "tags": ["spreadsheet", "google-workspace", "data-analytics"] }, { "type": "google_slides_v2", @@ -4791,11 +4561,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "google-workspace", - "document-processing", - "content-management" - ] + "tags": ["google-workspace", "document-processing", "content-management"] }, { "type": "google_tasks", @@ -4838,11 +4604,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "google-workspace", - "project-management", - "scheduling" - ] + "tags": ["google-workspace", "project-management", "scheduling"] }, { "type": "google_translate", @@ -4869,11 +4631,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "google-workspace", - "content-management", - "automation" - ] + "tags": ["google-workspace", "content-management", "automation"] }, { "type": "google_vault", @@ -4920,11 +4678,7 @@ "authType": "oauth", "category": "tools", "integrationType": "security", - "tags": [ - "google-workspace", - "secrets-management", - "document-processing" - ] + "tags": ["google-workspace", "secrets-management", "document-processing"] }, { "type": "grafana", @@ -5019,10 +4773,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "monitoring", - "data-analytics" - ] + "tags": ["monitoring", "data-analytics"] }, { "type": "grain", @@ -5118,10 +4869,7 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": [ - "meeting", - "note-taking" - ] + "tags": ["meeting", "note-taking"] }, { "type": "greenhouse", @@ -5184,9 +4932,7 @@ "authType": "api-key", "category": "tools", "integrationType": "hr", - "tags": [ - "hiring" - ] + "tags": ["hiring"] }, { "type": "greptile", @@ -5221,10 +4967,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "version-control", - "knowledge-base" - ] + "tags": ["version-control", "knowledge-base"] }, { "type": "hex", @@ -5307,10 +5050,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "data-warehouse", - "data-analytics" - ] + "tags": ["data-warehouse", "data-analytics"] }, { "type": "hubspot", @@ -5460,11 +5200,7 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": [ - "marketing", - "sales-engagement", - "customer-support" - ] + "tags": ["marketing", "sales-engagement", "customer-support"] }, { "type": "huggingface", @@ -5482,10 +5218,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "agentic" - ] + "tags": ["llm", "agentic"] }, { "type": "hunter", @@ -5528,10 +5261,7 @@ "authType": "api-key", "category": "tools", "integrationType": "sales-intelligence", - "tags": [ - "enrichment", - "sales-engagement" - ] + "tags": ["enrichment", "sales-engagement"] }, { "type": "image_generator", @@ -5549,10 +5279,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "image-generation", - "llm" - ] + "tags": ["image-generation", "llm"] }, { "type": "imap", @@ -5576,10 +5303,7 @@ "authType": "none", "category": "triggers", "integrationType": "email", - "tags": [ - "messaging", - "automation" - ] + "tags": ["messaging", "automation"] }, { "type": "incidentio", @@ -5774,10 +5498,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "incident-management", - "monitoring" - ] + "tags": ["incident-management", "monitoring"] }, { "type": "infisical", @@ -5816,9 +5537,7 @@ "authType": "api-key", "category": "tools", "integrationType": "security", - "tags": [ - "secrets-management" - ] + "tags": ["secrets-management"] }, { "type": "intercom_v2", @@ -5961,10 +5680,7 @@ "authType": "api-key", "category": "tools", "integrationType": "customer-support", - "tags": [ - "customer-support", - "messaging" - ] + "tags": ["customer-support", "messaging"] }, { "type": "jina", @@ -5991,10 +5707,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "knowledge-base" - ] + "tags": ["web-scraping", "knowledge-base"] }, { "type": "jira", @@ -6140,10 +5853,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "project-management", - "ticketing" - ] + "tags": ["project-management", "ticketing"] }, { "type": "jira_service_management", @@ -6246,11 +5956,7 @@ "authType": "oauth", "category": "tools", "integrationType": "customer-support", - "tags": [ - "customer-support", - "ticketing", - "incident-management" - ] + "tags": ["customer-support", "ticketing", "incident-management"] }, { "type": "kalshi_v2", @@ -6337,10 +6043,7 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": [ - "prediction-markets", - "data-analytics" - ] + "tags": ["prediction-markets", "data-analytics"] }, { "type": "knowledge", @@ -6440,11 +6143,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "monitoring", - "llm", - "data-analytics" - ] + "tags": ["monitoring", "llm", "data-analytics"] }, { "type": "lemlist", @@ -6521,11 +6220,7 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": [ - "sales-engagement", - "email-marketing", - "automation" - ] + "tags": ["sales-engagement", "email-marketing", "automation"] }, { "type": "linear", @@ -6932,10 +6627,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "project-management", - "ticketing" - ] + "tags": ["project-management", "ticketing"] }, { "type": "linkedin", @@ -6962,11 +6654,7 @@ "authType": "oauth", "category": "tools", "integrationType": "social", - "tags": [ - "marketing", - "sales-engagement", - "enrichment" - ] + "tags": ["marketing", "sales-engagement", "enrichment"] }, { "type": "linkup", @@ -6984,10 +6672,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "enrichment" - ] + "tags": ["web-scraping", "enrichment"] }, { "type": "loops", @@ -7046,11 +6731,7 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": [ - "email-marketing", - "marketing", - "automation" - ] + "tags": ["email-marketing", "marketing", "automation"] }, { "type": "luma", @@ -7093,11 +6774,7 @@ "authType": "api-key", "category": "tools", "integrationType": "productivity", - "tags": [ - "events", - "calendar", - "scheduling" - ] + "tags": ["events", "calendar", "scheduling"] }, { "type": "mailchimp", @@ -7408,11 +7085,7 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": [ - "email-marketing", - "marketing", - "automation" - ] + "tags": ["email-marketing", "marketing", "automation"] }, { "type": "mailgun", @@ -7463,10 +7136,7 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": [ - "messaging", - "email-marketing" - ] + "tags": ["messaging", "email-marketing"] }, { "type": "mem0", @@ -7497,11 +7167,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "knowledge-base", - "agentic" - ] + "tags": ["llm", "knowledge-base", "agentic"] }, { "type": "memory", @@ -7621,11 +7287,7 @@ "authType": "oauth", "category": "tools", "integrationType": "databases", - "tags": [ - "microsoft-365", - "data-warehouse", - "cloud" - ] + "tags": ["microsoft-365", "data-warehouse", "cloud"] }, { "type": "microsoft_excel_v2", @@ -7652,10 +7314,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "spreadsheet", - "microsoft-365" - ] + "tags": ["spreadsheet", "microsoft-365"] }, { "type": "microsoft_planner", @@ -7726,11 +7385,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "project-management", - "microsoft-365", - "ticketing" - ] + "tags": ["project-management", "microsoft-365", "ticketing"] }, { "type": "microsoft_teams", @@ -7811,10 +7466,7 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "microsoft-365" - ] + "tags": ["messaging", "microsoft-365"] }, { "type": "mistral_parse_v3", @@ -7832,10 +7484,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "document-processing", - "ocr" - ] + "tags": ["document-processing", "ocr"] }, { "type": "mongodb", @@ -7878,10 +7527,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "data-warehouse", - "cloud" - ] + "tags": ["data-warehouse", "cloud"] }, { "type": "mysql", @@ -7924,10 +7570,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "data-warehouse", - "data-analytics" - ] + "tags": ["data-warehouse", "data-analytics"] }, { "type": "neo4j", @@ -7974,10 +7617,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "data-warehouse", - "data-analytics" - ] + "tags": ["data-warehouse", "data-analytics"] }, { "type": "notion_v2", @@ -7995,11 +7635,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "note-taking", - "knowledge-base", - "content-management" - ] + "tags": ["note-taking", "knowledge-base", "content-management"] }, { "type": "obsidian", @@ -8078,10 +7714,7 @@ "authType": "api-key", "category": "tools", "integrationType": "documents", - "tags": [ - "note-taking", - "knowledge-base" - ] + "tags": ["note-taking", "knowledge-base"] }, { "type": "okta", @@ -8172,10 +7805,7 @@ "authType": "api-key", "category": "tools", "integrationType": "security", - "tags": [ - "identity", - "automation" - ] + "tags": ["identity", "automation"] }, { "type": "onedrive", @@ -8218,11 +7848,7 @@ "authType": "oauth", "category": "tools", "integrationType": "file-storage", - "tags": [ - "microsoft-365", - "cloud", - "document-processing" - ] + "tags": ["microsoft-365", "cloud", "document-processing"] }, { "type": "outlook", @@ -8277,11 +7903,7 @@ "authType": "oauth", "category": "tools", "integrationType": "email", - "tags": [ - "microsoft-365", - "messaging", - "automation" - ] + "tags": ["microsoft-365", "messaging", "automation"] }, { "type": "pagerduty", @@ -8324,10 +7946,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "incident-management", - "monitoring" - ] + "tags": ["incident-management", "monitoring"] }, { "type": "parallel_ai", @@ -8358,11 +7977,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "llm", - "agentic" - ] + "tags": ["web-scraping", "llm", "agentic"] }, { "type": "perplexity", @@ -8389,11 +8004,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "web-scraping", - "agentic" - ] + "tags": ["llm", "web-scraping", "agentic"] }, { "type": "pinecone", @@ -8432,10 +8043,7 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": [ - "vector-search", - "knowledge-base" - ] + "tags": ["vector-search", "knowledge-base"] }, { "type": "pipedrive", @@ -8526,10 +8134,7 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": [ - "sales-engagement", - "project-management" - ] + "tags": ["sales-engagement", "project-management"] }, { "type": "polymarket", @@ -8628,10 +8233,7 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": [ - "prediction-markets", - "data-analytics" - ] + "tags": ["prediction-markets", "data-analytics"] }, { "type": "postgresql", @@ -8674,10 +8276,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "data-warehouse", - "data-analytics" - ] + "tags": ["data-warehouse", "data-analytics"] }, { "type": "posthog", @@ -8868,10 +8467,7 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": [ - "data-analytics", - "monitoring" - ] + "tags": ["data-analytics", "monitoring"] }, { "type": "pulse_v2", @@ -8889,10 +8485,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "document-processing", - "ocr" - ] + "tags": ["document-processing", "ocr"] }, { "type": "qdrant", @@ -8923,10 +8516,7 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": [ - "vector-search", - "knowledge-base" - ] + "tags": ["vector-search", "knowledge-base"] }, { "type": "quiver", @@ -8957,9 +8547,7 @@ "authType": "api-key", "category": "tools", "integrationType": "design", - "tags": [ - "image-generation" - ] + "tags": ["image-generation"] }, { "type": "reddit", @@ -9046,10 +8634,7 @@ "authType": "oauth", "category": "tools", "integrationType": "social", - "tags": [ - "content-management", - "web-scraping" - ] + "tags": ["content-management", "web-scraping"] }, { "type": "redis", @@ -9156,10 +8741,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "cloud", - "data-warehouse" - ] + "tags": ["cloud", "data-warehouse"] }, { "type": "reducto_v2", @@ -9177,10 +8759,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "document-processing", - "ocr" - ] + "tags": ["document-processing", "ocr"] }, { "type": "resend", @@ -9231,10 +8810,7 @@ "authType": "none", "category": "tools", "integrationType": "email", - "tags": [ - "email-marketing", - "messaging" - ] + "tags": ["email-marketing", "messaging"] }, { "type": "revenuecat", @@ -9293,10 +8869,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ecommerce", - "tags": [ - "payments", - "subscriptions" - ] + "tags": ["payments", "subscriptions"] }, { "type": "rippling", @@ -9390,7 +8963,8 @@ "triggerCount": 0, "authType": "api-key", "category": "tools", - "integrationType": "hr" + "integrationType": "hr", + "tags": ["hiring"] }, { "type": "s3", @@ -9429,10 +9003,7 @@ "authType": "none", "category": "tools", "integrationType": "file-storage", - "tags": [ - "cloud", - "data-warehouse" - ] + "tags": ["cloud", "data-warehouse"] }, { "type": "salesforce", @@ -9591,10 +9162,7 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": [ - "sales-engagement", - "customer-support" - ] + "tags": ["sales-engagement", "customer-support"] }, { "type": "search", @@ -9612,10 +9180,7 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "seo" - ] + "tags": ["web-scraping", "seo"] }, { "type": "sendgrid", @@ -9698,10 +9263,7 @@ "authType": "api-key", "category": "tools", "integrationType": "email", - "tags": [ - "email-marketing", - "messaging" - ] + "tags": ["email-marketing", "messaging"] }, { "type": "sentry", @@ -9768,10 +9330,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "error-tracking", - "monitoring" - ] + "tags": ["error-tracking", "monitoring"] }, { "type": "serper", @@ -9789,10 +9348,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "seo" - ] + "tags": ["web-scraping", "seo"] }, { "type": "servicenow", @@ -9827,11 +9383,7 @@ "authType": "none", "category": "tools", "integrationType": "customer-support", - "tags": [ - "customer-support", - "ticketing", - "incident-management" - ] + "tags": ["customer-support", "ticketing", "incident-management"] }, { "type": "sftp", @@ -9874,10 +9426,7 @@ "authType": "none", "category": "tools", "integrationType": "file-storage", - "tags": [ - "cloud", - "automation" - ] + "tags": ["cloud", "automation"] }, { "type": "sharepoint", @@ -9928,11 +9477,7 @@ "authType": "oauth", "category": "tools", "integrationType": "documents", - "tags": [ - "microsoft-365", - "content-management", - "document-processing" - ] + "tags": ["microsoft-365", "content-management", "document-processing"] }, { "type": "shopify", @@ -10035,10 +9580,7 @@ "authType": "oauth", "category": "tools", "integrationType": "ecommerce", - "tags": [ - "payments", - "subscriptions" - ] + "tags": ["payments", "subscriptions"] }, { "type": "similarweb", @@ -10077,11 +9619,7 @@ "authType": "api-key", "category": "tools", "integrationType": "analytics", - "tags": [ - "marketing", - "data-analytics", - "seo" - ] + "tags": ["marketing", "data-analytics", "seo"] }, { "type": "slack", @@ -10206,11 +9744,7 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "webhooks", - "automation" - ] + "tags": ["messaging", "webhooks", "automation"] }, { "type": "smtp", @@ -10228,10 +9762,7 @@ "authType": "none", "category": "tools", "integrationType": "email", - "tags": [ - "email-marketing", - "messaging" - ] + "tags": ["email-marketing", "messaging"] }, { "type": "stt_v2", @@ -10249,10 +9780,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "speech-to-text", - "document-processing" - ] + "tags": ["speech-to-text", "document-processing"] }, { "type": "ssh", @@ -10323,10 +9851,7 @@ "authType": "none", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "cloud", - "automation" - ] + "tags": ["cloud", "automation"] }, { "type": "stagehand", @@ -10353,11 +9878,7 @@ "authType": "api-key", "category": "tools", "integrationType": "automation", - "tags": [ - "web-scraping", - "automation", - "agentic" - ] + "tags": ["web-scraping", "automation", "agentic"] }, { "type": "stripe", @@ -10582,11 +10103,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ecommerce", - "tags": [ - "payments", - "subscriptions", - "webhooks" - ] + "tags": ["payments", "subscriptions", "webhooks"] }, { "type": "supabase", @@ -10693,11 +10210,7 @@ "authType": "api-key", "category": "tools", "integrationType": "databases", - "tags": [ - "cloud", - "data-warehouse", - "vector-search" - ] + "tags": ["cloud", "data-warehouse", "vector-search"] }, { "type": "tavily", @@ -10732,10 +10245,7 @@ "authType": "api-key", "category": "tools", "integrationType": "search", - "tags": [ - "web-scraping", - "enrichment" - ] + "tags": ["web-scraping", "enrichment"] }, { "type": "telegram", @@ -10788,11 +10298,7 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "webhooks", - "automation" - ] + "tags": ["messaging", "webhooks", "automation"] }, { "type": "tts", @@ -10810,10 +10316,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "text-to-speech", - "llm" - ] + "tags": ["text-to-speech", "llm"] }, { "type": "tinybird", @@ -10840,10 +10343,7 @@ "authType": "none", "category": "tools", "integrationType": "analytics", - "tags": [ - "data-warehouse", - "data-analytics" - ] + "tags": ["data-warehouse", "data-analytics"] }, { "type": "translate", @@ -10861,10 +10361,7 @@ "authType": "none", "category": "tools", "integrationType": "ai", - "tags": [ - "document-processing", - "llm" - ] + "tags": ["document-processing", "llm"] }, { "type": "trello", @@ -10907,10 +10404,7 @@ "authType": "oauth", "category": "tools", "integrationType": "productivity", - "tags": [ - "project-management", - "ticketing" - ] + "tags": ["project-management", "ticketing"] }, { "type": "twilio_sms", @@ -10928,10 +10422,7 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "automation" - ] + "tags": ["messaging", "automation"] }, { "type": "twilio_voice", @@ -10968,10 +10459,7 @@ "authType": "none", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "text-to-speech" - ] + "tags": ["messaging", "text-to-speech"] }, { "type": "typeform", @@ -11028,10 +10516,7 @@ "authType": "api-key", "category": "tools", "integrationType": "documents", - "tags": [ - "forms", - "data-analytics" - ] + "tags": ["forms", "data-analytics"] }, { "type": "upstash", @@ -11114,10 +10599,7 @@ "authType": "none", "category": "tools", "integrationType": "databases", - "tags": [ - "cloud", - "data-warehouse" - ] + "tags": ["cloud", "data-warehouse"] }, { "type": "vercel", @@ -11336,10 +10818,7 @@ "authType": "api-key", "category": "tools", "integrationType": "developer-tools", - "tags": [ - "cloud", - "ci-cd" - ] + "tags": ["cloud", "ci-cd"] }, { "type": "video_generator_v2", @@ -11357,10 +10836,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "video-generation", - "llm" - ] + "tags": ["video-generation", "llm"] }, { "type": "vision_v2", @@ -11378,11 +10854,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "document-processing", - "ocr" - ] + "tags": ["llm", "document-processing", "ocr"] }, { "type": "wealthbox", @@ -11425,10 +10897,7 @@ "authType": "oauth", "category": "tools", "integrationType": "crm", - "tags": [ - "sales-engagement", - "customer-support" - ] + "tags": ["sales-engagement", "customer-support"] }, { "type": "webflow", @@ -11488,10 +10957,7 @@ "authType": "oauth", "category": "tools", "integrationType": "design", - "tags": [ - "content-management", - "seo" - ] + "tags": ["content-management", "seo"] }, { "type": "whatsapp", @@ -11515,10 +10981,7 @@ "authType": "api-key", "category": "tools", "integrationType": "communication", - "tags": [ - "messaging", - "automation" - ] + "tags": ["messaging", "automation"] }, { "type": "wikipedia", @@ -11553,10 +11016,7 @@ "authType": "none", "category": "tools", "integrationType": "search", - "tags": [ - "knowledge-base", - "web-scraping" - ] + "tags": ["knowledge-base", "web-scraping"] }, { "type": "wordpress", @@ -11679,10 +11139,7 @@ "authType": "oauth", "category": "tools", "integrationType": "design", - "tags": [ - "content-management", - "seo" - ] + "tags": ["content-management", "seo"] }, { "type": "workday", @@ -11741,10 +11198,7 @@ "authType": "none", "category": "tools", "integrationType": "hr", - "tags": [ - "hiring", - "project-management" - ] + "tags": ["hiring", "project-management"] }, { "type": "x", @@ -11875,10 +11329,7 @@ "authType": "oauth", "category": "tools", "integrationType": "social", - "tags": [ - "marketing", - "messaging" - ] + "tags": ["marketing", "messaging"] }, { "type": "youtube", @@ -11933,11 +11384,7 @@ "authType": "api-key", "category": "tools", "integrationType": "media", - "tags": [ - "google-workspace", - "marketing", - "content-management" - ] + "tags": ["google-workspace", "marketing", "content-management"] }, { "type": "zendesk", @@ -12060,10 +11507,7 @@ "authType": "none", "category": "tools", "integrationType": "customer-support", - "tags": [ - "customer-support", - "ticketing" - ] + "tags": ["customer-support", "ticketing"] }, { "type": "zep", @@ -12118,11 +11562,7 @@ "authType": "api-key", "category": "tools", "integrationType": "ai", - "tags": [ - "llm", - "knowledge-base", - "agentic" - ] + "tags": ["llm", "knowledge-base", "agentic"] }, { "type": "zoom", @@ -12181,10 +11621,6 @@ "authType": "oauth", "category": "tools", "integrationType": "communication", - "tags": [ - "meeting", - "calendar", - "scheduling" - ] + "tags": ["meeting", "calendar", "scheduling"] } -] \ No newline at end of file +] diff --git a/apps/sim/blocks/blocks/rippling.ts b/apps/sim/blocks/blocks/rippling.ts index c4a4b8a2a1..5425c7a69a 100644 --- a/apps/sim/blocks/blocks/rippling.ts +++ b/apps/sim/blocks/blocks/rippling.ts @@ -11,7 +11,7 @@ export const RipplingBlock: BlockConfig = { docsLink: 'https://docs.sim.ai/tools/rippling', category: 'tools', integrationType: IntegrationType.HR, - tags: [], + tags: ['hiring'], bgColor: '#FFCC1C', icon: RipplingIcon, authMode: AuthMode.ApiKey, @@ -317,20 +317,49 @@ export const RipplingBlock: BlockConfig = { ], config: { tool: (params) => `rippling_${params.operation}`, - params: (params) => ({ - ...params, - ...(params.limit && { limit: Number(params.limit) }), - ...(params.offset && { offset: Number(params.offset) }), - ...(params.groupVersion && { version: Number(params.groupVersion) }), - ...(params.groupName && { name: params.groupName }), - ...(params.candidatePhone && { phone: params.candidatePhone }), - ...(params.candidateDepartment && { department: params.candidateDepartment }), - ...(params.candidateStartDate && { startDate: params.candidateStartDate }), - ...(params.nextCursor && { next: params.nextCursor }), - ...(params.users && { - users: typeof params.users === 'string' ? JSON.parse(params.users) : params.users, - }), - }), + params: (params) => { + const mapped: Record = { + apiKey: params.apiKey, + operation: params.operation, + } + + if (params.employeeId) mapped.employeeId = params.employeeId + if (params.leaveRequestId) mapped.leaveRequestId = params.leaveRequestId + if (params.action) mapped.action = params.action + if (params.roleId) mapped.roleId = params.roleId + if (params.spokeId) mapped.spokeId = params.spokeId + if (params.groupId) mapped.groupId = params.groupId + if (params.firstName) mapped.firstName = params.firstName + if (params.lastName) mapped.lastName = params.lastName + if (params.email) mapped.email = params.email + if (params.jobTitle) mapped.jobTitle = params.jobTitle + if (params.startDate) mapped.startDate = params.startDate + if (params.endDate) mapped.endDate = params.endDate + if (params.status) mapped.status = params.status + if (params.managedBy) mapped.managedBy = params.managedBy + + if (params.limit != null && params.limit !== '') mapped.limit = Number(params.limit) + if (params.offset != null && params.offset !== '') mapped.offset = Number(params.offset) + if (params.groupVersion) mapped.version = Number(params.groupVersion) + if (params.groupName) mapped.name = params.groupName + if (params.candidatePhone) mapped.phone = params.candidatePhone + if (params.candidateDepartment) mapped.department = params.candidateDepartment + if (params.candidateStartDate) mapped.startDate = params.candidateStartDate + if (params.nextCursor) mapped.next = params.nextCursor + + if (params.users) { + try { + mapped.users = + typeof params.users === 'string' ? JSON.parse(params.users) : params.users + } catch { + throw new Error( + 'Invalid JSON for "User IDs" field. Expected an array like ["user-id-1", "user-id-2"].' + ) + } + } + + return mapped + }, }, }, From a73a0fb425d76bc23b303b7c48ca69ecabe43836 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 25 Mar 2026 11:06:36 -0700 Subject: [PATCH 3/6] fix(rippling): guard startDate by operation and clarify totalCount descriptions - Guard startDate/endDate with operation check to prevent candidateStartDate from clobbering date filters on leave/activity operations - Update totalCount output descriptions on paginated tools to clarify it reflects page size, not total record count --- apps/sim/blocks/blocks/rippling.ts | 8 +++++--- apps/sim/tools/rippling/get_company_activity.ts | 2 +- apps/sim/tools/rippling/list_custom_fields.ts | 2 +- apps/sim/tools/rippling/list_departments.ts | 2 +- apps/sim/tools/rippling/list_employees.ts | 2 +- apps/sim/tools/rippling/list_employees_with_terminated.ts | 2 +- apps/sim/tools/rippling/list_leave_balances.ts | 2 +- apps/sim/tools/rippling/list_levels.ts | 2 +- apps/sim/tools/rippling/list_teams.ts | 2 +- apps/sim/tools/rippling/list_work_locations.ts | 2 +- 10 files changed, 14 insertions(+), 12 deletions(-) diff --git a/apps/sim/blocks/blocks/rippling.ts b/apps/sim/blocks/blocks/rippling.ts index 5425c7a69a..3ddb24522b 100644 --- a/apps/sim/blocks/blocks/rippling.ts +++ b/apps/sim/blocks/blocks/rippling.ts @@ -333,8 +333,9 @@ export const RipplingBlock: BlockConfig = { if (params.lastName) mapped.lastName = params.lastName if (params.email) mapped.email = params.email if (params.jobTitle) mapped.jobTitle = params.jobTitle - if (params.startDate) mapped.startDate = params.startDate - if (params.endDate) mapped.endDate = params.endDate + if (params.startDate && params.operation !== 'push_candidate') + mapped.startDate = params.startDate + if (params.endDate && params.operation !== 'push_candidate') mapped.endDate = params.endDate if (params.status) mapped.status = params.status if (params.managedBy) mapped.managedBy = params.managedBy @@ -344,7 +345,8 @@ export const RipplingBlock: BlockConfig = { if (params.groupName) mapped.name = params.groupName if (params.candidatePhone) mapped.phone = params.candidatePhone if (params.candidateDepartment) mapped.department = params.candidateDepartment - if (params.candidateStartDate) mapped.startDate = params.candidateStartDate + if (params.candidateStartDate && params.operation === 'push_candidate') + mapped.startDate = params.candidateStartDate if (params.nextCursor) mapped.next = params.nextCursor if (params.users) { diff --git a/apps/sim/tools/rippling/get_company_activity.ts b/apps/sim/tools/rippling/get_company_activity.ts index af786d220f..41e2759140 100644 --- a/apps/sim/tools/rippling/get_company_activity.ts +++ b/apps/sim/tools/rippling/get_company_activity.ts @@ -114,7 +114,7 @@ export const ripplingGetCompanyActivityTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of activity events returned', + description: 'Number of activity events returned on this page', }, nextCursor: { type: 'string', diff --git a/apps/sim/tools/rippling/list_custom_fields.ts b/apps/sim/tools/rippling/list_custom_fields.ts index efe986e530..d24204f34f 100644 --- a/apps/sim/tools/rippling/list_custom_fields.ts +++ b/apps/sim/tools/rippling/list_custom_fields.ts @@ -90,7 +90,7 @@ export const ripplingListCustomFieldsTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of custom fields returned', + description: 'Number of custom fields returned on this page', }, }, } diff --git a/apps/sim/tools/rippling/list_departments.ts b/apps/sim/tools/rippling/list_departments.ts index e41fdb7e24..830432af6b 100644 --- a/apps/sim/tools/rippling/list_departments.ts +++ b/apps/sim/tools/rippling/list_departments.ts @@ -88,7 +88,7 @@ export const ripplingListDepartmentsTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of departments returned', + description: 'Number of departments returned on this page', }, }, } diff --git a/apps/sim/tools/rippling/list_employees.ts b/apps/sim/tools/rippling/list_employees.ts index fb1067f15d..bf2782e42b 100644 --- a/apps/sim/tools/rippling/list_employees.ts +++ b/apps/sim/tools/rippling/list_employees.ts @@ -106,7 +106,7 @@ export const ripplingListEmployeesTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of employees returned', + description: 'Number of employees returned on this page', }, }, } diff --git a/apps/sim/tools/rippling/list_employees_with_terminated.ts b/apps/sim/tools/rippling/list_employees_with_terminated.ts index 9eddcf856d..86924bd944 100644 --- a/apps/sim/tools/rippling/list_employees_with_terminated.ts +++ b/apps/sim/tools/rippling/list_employees_with_terminated.ts @@ -107,7 +107,7 @@ export const ripplingListEmployeesWithTerminatedTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of employees returned', + description: 'Number of employees returned on this page', }, }, } diff --git a/apps/sim/tools/rippling/list_leave_balances.ts b/apps/sim/tools/rippling/list_leave_balances.ts index a7509679cc..ff0e4cc23a 100644 --- a/apps/sim/tools/rippling/list_leave_balances.ts +++ b/apps/sim/tools/rippling/list_leave_balances.ts @@ -101,7 +101,7 @@ export const ripplingListLeaveBalancesTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of leave balances returned', + description: 'Number of leave balances returned on this page', }, }, } diff --git a/apps/sim/tools/rippling/list_levels.ts b/apps/sim/tools/rippling/list_levels.ts index 0739b236aa..55d679f95c 100644 --- a/apps/sim/tools/rippling/list_levels.ts +++ b/apps/sim/tools/rippling/list_levels.ts @@ -85,7 +85,7 @@ export const ripplingListLevelsTool: ToolConfig< }, totalCount: { type: 'number', - description: 'Total number of levels returned', + description: 'Number of levels returned on this page', }, }, } diff --git a/apps/sim/tools/rippling/list_teams.ts b/apps/sim/tools/rippling/list_teams.ts index f36891b579..5a906e609a 100644 --- a/apps/sim/tools/rippling/list_teams.ts +++ b/apps/sim/tools/rippling/list_teams.ts @@ -83,7 +83,7 @@ export const ripplingListTeamsTool: ToolConfig Date: Wed, 25 Mar 2026 11:20:09 -0700 Subject: [PATCH 4/6] fix(rippling): use null-safe guard for groupVersion param --- apps/sim/blocks/blocks/rippling.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/sim/blocks/blocks/rippling.ts b/apps/sim/blocks/blocks/rippling.ts index 3ddb24522b..898f36fe4a 100644 --- a/apps/sim/blocks/blocks/rippling.ts +++ b/apps/sim/blocks/blocks/rippling.ts @@ -341,7 +341,8 @@ export const RipplingBlock: BlockConfig = { if (params.limit != null && params.limit !== '') mapped.limit = Number(params.limit) if (params.offset != null && params.offset !== '') mapped.offset = Number(params.offset) - if (params.groupVersion) mapped.version = Number(params.groupVersion) + if (params.groupVersion != null && params.groupVersion !== '') + mapped.version = Number(params.groupVersion) if (params.groupName) mapped.name = params.groupName if (params.candidatePhone) mapped.phone = params.candidatePhone if (params.candidateDepartment) mapped.department = params.candidateDepartment From c06ffdc4e18e86d76564a4be88e76bfc268f6848 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 25 Mar 2026 11:21:24 -0700 Subject: [PATCH 5/6] fix(rippling): remove operation field from tool params payload --- apps/sim/blocks/blocks/rippling.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/sim/blocks/blocks/rippling.ts b/apps/sim/blocks/blocks/rippling.ts index 898f36fe4a..ad491435d0 100644 --- a/apps/sim/blocks/blocks/rippling.ts +++ b/apps/sim/blocks/blocks/rippling.ts @@ -320,7 +320,6 @@ export const RipplingBlock: BlockConfig = { params: (params) => { const mapped: Record = { apiKey: params.apiKey, - operation: params.operation, } if (params.employeeId) mapped.employeeId = params.employeeId From 6ed19dd0acfae60c77f0b1b6a5b254dc16c02c45 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 25 Mar 2026 11:30:14 -0700 Subject: [PATCH 6/6] fix(rippling): add input validation for action param and empty group update body --- apps/sim/tools/rippling/process_leave_request.ts | 9 +++++++-- apps/sim/tools/rippling/update_group.ts | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/sim/tools/rippling/process_leave_request.ts b/apps/sim/tools/rippling/process_leave_request.ts index eefd0f757b..4589a3b16f 100644 --- a/apps/sim/tools/rippling/process_leave_request.ts +++ b/apps/sim/tools/rippling/process_leave_request.ts @@ -35,8 +35,13 @@ export const ripplingProcessLeaveRequestTool: ToolConfig< }, request: { - url: (params) => - `https://api.rippling.com/platform/api/leave_requests/${encodeURIComponent(params.leaveRequestId.trim())}/process?action=${encodeURIComponent(params.action.trim())}`, + url: (params) => { + const action = params.action.trim() + if (action !== 'approve' && action !== 'decline') { + throw new Error(`Invalid action "${action}". Must be "approve" or "decline".`) + } + return `https://api.rippling.com/platform/api/leave_requests/${encodeURIComponent(params.leaveRequestId.trim())}/process?action=${encodeURIComponent(action)}` + }, method: 'POST', headers: (params) => ({ Authorization: `Bearer ${params.apiKey}`, diff --git a/apps/sim/tools/rippling/update_group.ts b/apps/sim/tools/rippling/update_group.ts index cd31572f79..c1c7bd5484 100644 --- a/apps/sim/tools/rippling/update_group.ts +++ b/apps/sim/tools/rippling/update_group.ts @@ -72,6 +72,11 @@ export const ripplingUpdateGroupTool: ToolConfig< if (params.version !== undefined) { body.version = params.version } + if (Object.keys(body).length === 0) { + throw new Error( + 'At least one field (name, spokeId, users, or version) must be provided to update a group.' + ) + } return body }, },