Skip to content

feat: add Workable ATS integration - #663

Open
iprasen wants to merge 1 commit into
revertinc:mainfrom
iprasen:feat/workable-ats-integration-551
Open

iprasen wants to merge 1 commit into
revertinc:mainfrom
iprasen:feat/workable-ats-integration-551

Conversation

@iprasen

@iprasen iprasen commented Sep 11, 2026

Copy link
Copy Markdown

Resolves #551
Fixes #551

/claim #551

Summary of Changes

This PR implements the full, production-grade Workable ATS integration across Revert backend, Prisma database schema/seed, unified CRM transforms, client UI, and JS SDK.

1. Database & Configuration

  • Prisma Schema & Enum: Added workable to TP_ID enum in schema.prisma.
  • Database Migration: Added SQL migration 20260907130000_workable_enum/migration.sql with ALTER TYPE "TP_ID" ADD VALUE 'workable';.
  • Constants: Registered workable in ATS_TP_ID, DEFAULT_SCOPE, and mapIntegrationIdToIntegrationName.
  • Environment & Config: Added WORKABLE_CLIENT_ID, WORKABLE_CLIENT_SECRET, WORKABLE_AUTH_URL, and WORKABLE_TOKEN_URL in config.ts and .env.example.
  • Database Seed & Field Mappings: Injected 77 field mappings across Candidate, Job, Offer, and Department in fields.ts and enabled seeding in seed.ts.

2. Dual Authentication & Routing

  • WorkableAuthHandler: Implemented dual authentication in routes/v1/ats/authHandlers/workable.ts:
    • Direct API Access Token (Basic Auth): Takes token from Workable Settings > Integrations > Access Token, persists to connection with active status, and emits sendConnectionAddedEvent.
    • OAuth2 Flow: Exchanges code for access token via Workable OAuth token endpoint, fetches account profile, and saves connection.
  • OAuth Callback: Wired /oauth-callback in routes/v1/ats/auth.ts to automatically route between OAuth and Direct API Token based on available app credentials.
  • Token Refresh & Metadata: Wired automated refresh in services/auth.ts and registered official Workable logo/metadata in services/metadata.ts.

3. Unified ATS Endpoints

  • Candidate Service (services/ats/candidate.ts):
    • getCandidate: Fetches /candidates/:id and unifies.
    • getCandidates: Fetches /candidates (or /jobs/:shortcode/candidates) with cursor pagination and unifies.
    • createCandidate: Creates candidate; routes to /jobs/:shortcode/candidates if shortcode or job_id is supplied, else /candidates.
    • updateCandidate: Updates candidate via PATCH /candidates/:id.
    • deleteCandidate: Deletes candidate via DELETE /candidates/:id.
  • Job Service (services/ats/job.ts):
    • getJob: Fetches /jobs/:shortcode and unifies.
    • getJobs: Fetches /jobs with cursor pagination and unifies.
    • createJob, updateJob, deleteJob: Standard unsupported responses matching Revert ATS architecture.
  • Department Service (services/ats/department.ts):
    • getDepartments: Fetches /departments with cursor pagination and unifies.
    • getDepartment: Resolves specific department from /departments by ID/name.
  • Offer Service (services/ats/offer.ts):
    • getOffer: Fetches /offers/:id and unifies.
    • getOffers: Fetches /offers or /candidates/:id/offer and unifies.
  • Proxy Service (services/ats/proxy.ts):
    • Passthrough proxy tunneling arbitrary requests to https://{subdomain}.workable.com/spi/v3/{path} with Bearer auth headers.

4. Transforms & Normalizers

  • Preprocess Normalizers (helpers/crm/transform/preprocess.ts): Added normalizers for Candidate (names, emails, phones, stages, application shortcodes), Job (shortcode, department, status mapping), Offer (status, candidate/job links), and Department.
  • Disunify Payload (helpers/crm/transform/disunify.ts): Added Workable candidate creation payload disunification (candidate: { firstname, lastname, name, email, phone, headline, summary }).

5. Frontend UI & JS SDK

  • Edit Credentials (EditCredentials.tsx): Added Subdomain / Organisation URL input and validation check for Workable.
  • Client Metadata (enums/metadata.ts): Added Workable app info, description, and logo.
  • Client OAuth Callback (oauth/index.tsx): Included workable in ATS /oauth-callback handler.
  • JS SDK (packages/js/src/index.ts): Added Workable popup connect flow supporting direct API key modal input or OAuth popup.

Verification & Testing

  • 30 Automated Unit Tests (100% PASS):
    ./node_modules/.bin/jest --config=packages/backend/jest.config.json packages/backend/helpers/ats/workable.test.ts --forceExit
    • URL normalization (subdomains, full hosts, https, spi/v3 paths)
    • Bearer auth header generation
    • Collection & resource extraction
    • Cursor pagination parsing (since_id, after_id, cursor, paging.next_id)
    • Authenticated request execution
    • Preprocess normalizers for all 4 ATS entities
    • Candidate creation disunification
    • Basic auth handler execution and webhook emission
  • Prettier Code Formatting:
    ./node_modules/.bin/prettier --check <all changed files> -> All matched files use Prettier code style!

- Added workable to TP_ID enum, migration, common constants, and config
- Added Prisma field mappings (77 fields) for Candidate, Job, Offer, and Department
- Added preprocess and disunify normalizers for Workable ATS entities
- Added WorkableAuthHandler supporting both Direct API Key/Token and OAuth2 flows
- Wired token refresh service and metadata endpoint for Workable
- Implemented full ATS endpoints in candidate, job, department, offer, and proxy services
- Added client UI org URL input prompt, metadata, and oauth callback support
- Added JS SDK connect flow for Workable
- Added comprehensive unit test suite covering helpers, transforms, and auth (30/30 passing)
- Formatted all modified files with Prettier
@github-actions

Copy link
Copy Markdown

Thank you for following the naming conventions for pull request titles! 🙏

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REVER-51] Workable Integration

1 participant