
Workable ships a hosted MCP server that runs every call as the signed-in member, and a REST API reached through admin-generated account tokens on each customer's own subdomain. The two overlap heavily on jobs and candidates. They split on identity: one path knows who is acting, the other needs your code to say so on every write. This guide compares what each path lets a recruiting agent do, how attribution works, and how to run either across many customer companies in production.
Your product sits next to your customers' applicant tracking system. Its agent needs to tell a recruiting lead which Senior Backend Engineer candidates have sat in phone screen for more than a week, drop a screening summary on every new applicant's timeline, flag a candidate who already applied to a different role last quarter, and move people forward once an interview panel signs off. Every customer runs their own Workable account on their own subdomain. Workable now hosts an official MCP server and markets it to exactly these users. It also has a REST API with scoped tokens and signed webhooks. The two overlap heavily on candidates and jobs. They split on identity: one runs as the signed-in member, the other as an account-wide token that you have to attribute yourself. Here's how to pick.
The Workable MCP server is hosted by Workable at https://mcp.workable.com/mcp over Streamable HTTP, in what its docs call stateless JSON mode, with no SSE. Nothing runs locally. Workable announced general availability on May 13, 2026 with 38 tools, available on all plans at no extra cost, and by August 2026 it had grown to 94. The additions include advanced candidate and employee search, performance review cycles, member administration, and candidate write tools. The two advanced search capabilities require a Premier+ or Enterprise plan.
Clients authenticate with OAuth 2.0. The server publishes /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource and supports Dynamic Client Registration (DCR) under RFC 7591. Workable's help center has guides for Claude, ChatGPT, Cursor, and Microsoft Copilot Studio, and adds one catch: redirect URIs must be on a pre-approved list, and an unlisted one fails with a redirect URI mismatch until Workable Support adds it.
The first call is get_accounts, which lists every Workable account the member can reach. Every other tool takes that account's subdomain as an account parameter. Representative tools include get_candidates, search_candidates_detailed, move_candidate, disqualify_candidate, add_comment, upsert_candidate_rating, approve_offer, create_requisition, get_timeoff_requests, clock_in, and submit_review.
The Workable API v3 is REST at https://{subdomain}.workable.com/spi/v3/, where the subdomain is the customer's account, found under Settings > Company profile. It covers jobs and their stages, members, recruiters, and application questions; candidates, their activities, files, comments, ratings, tags, and custom attributes; offers; requisitions under Workable's Hiring Plan; departments and legal entities; scheduled events such as interviews; employees, documents, and the org chart; time off; time tracking; and webhook subscriptions. Lists page with since_id and max_id and return an absolute paging.next URL.
Three token types reach it:
The MCP column is wider than most vendor servers in this series. Workable did not ship a read-only demo; it ships stage moves, disqualifications, offer approvals, requisition approvals, member invites, and review sign-offs. For a recruiter in Claude, the gap to the API is small. The gaps that remain are structural: there is no event delivery, no way to create an employee record, and no way to run without a human starting the conversation.
The API column has its own gap, and it comes from the token, not the endpoints. Offer approval through the API requires a user-level token, which a self-serve account token is not. An agent that approves offers on the API path needs either Workable partner status or a human approving in Workable itself.
"Which Senior Backend Engineer candidates have been in phone screen for more than seven days" on the raw API means listing jobs to find the shortcode, reading that job's stages to learn the exact slug Workable uses for phone screen at this customer, listing candidates filtered by shortcode and stage, following paging.next, and reading each candidate's activity stream to find when they were moved into the stage. At 10 requests per 10 seconds on an account token, 40 candidates takes over 40 seconds of throttled calls, and every response lands in the model's context.
Workable MCP handles the identity and account plumbing for you. get_accounts resolves which subdomain to use, search_jobs finds a job by partial title and returns its shortcode, and search_candidates_detailed runs a filtered, sorted query across open jobs in one call on the plans that include it. Setup is a custom connector URL and a Workable sign-in. Writing the schema is the hard part. Not the API call.
The tradeoff is that Workable owns the surface, and it moves fast: 38 tools in May, 94 by August. Some of those tools carry hard edges that its own docs call out. submit_review and sign_review are final. update_candidate_tags replaces the whole tag list. Updating an approved requisition sends it back for approval. An agent tuned against today's tool set changes behavior when Workable ships, without a release on your side.
On the MCP path, auth is OAuth in the browser, and the result is a member-level identity. Workable states that each session is limited to the authenticated user's role and job assignments: a hiring manager collaborating on two jobs sees those two pipelines, a reviewer sees what reviewers see, and actions are recorded under that member. Workable's own clients need no setup. Your own agent registers itself through DCR, but its redirect URI still has to be on Workable's approved list.
On the direct API path, self-serve access means an account token. An admin generates it, picks scopes, and picks an expiry. It is tied to the account, not to the admin's job assignments, so a token with r_candidates reads every candidate in every job, including confidential roles a given recruiter was never assigned. Renewing an expired token keeps the same token value, which is convenient for integrations and means a leaked token that gets renewed stays leaked.
Writes on an account token raise a question MCP never does: who did this? Workable answers with a parameter. Moving, disqualifying, and reverting a candidate all require a member_id in the body, described as "the member performing" the action. Scalekit's connector docs add that on HR endpoints such as employee reads and updates, member_id is the "member whose access level is used." The account token proves your integration may act. The member_id decides whose name goes on the action and, for HR data, whose permissions filter the result.
That makes member_id an authorization input. Let the model fill it, and a prompt that says "do this as the head of people" can read employee records with an HR admin's access level. What the user can't do, the agent can't do, but only if your code, not the model, chooses the member.
In a multi-tenant B2B agent, MCP gives you a credential per user and the direct API gives you a credential per user. In neither case does the path itself solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.
Workable shifts where the boundary sits on the API path. Because account tokens are admin-generated and account-wide, the realistic unit is one credential per customer company, not one per recruiter. Per-user isolation then lives in two places you build: the mapping from your signed-in user to their Workable member_id, and the tool surface you expose to the model for that user. Get the first wrong and actions are attributed to the wrong recruiter. Get the second wrong and a hiring manager's question runs with access to every confidential requisition in the account.
Recommended reading: access control for multi-tenant AI agents
On the MCP path, Workable hosts the server, owns the schemas, and enforces each member's access. You own the OAuth session in each client, the redirect URI approval if you bring your own client, and the gaps. Nothing happens when a candidate applies at 03:00, because tools only run inside a conversation. Writes are live and some are irreversible, so a human confirming each one is part of the design, not a nicety.
On the API path, you own pagination, retries, the token lifecycle, and attribution. Workable's rate limits are 10 requests per 10 seconds for account tokens and 50 for OAuth and partner tokens, enforced per client, with X-Rate-Limit-Limit, X-Rate-Limit-Remaining, and X-Rate-Limit-Reset on every response and 429 past the limit. Ten requests per 10 seconds is shared by every workload on that customer's token: your agent, your nightly sync, and the reconciliation job. Token expiry is a calendar problem, not a refresh problem. A token issued for 90 days stops working on day 91 unless an admin at the customer renews it, so you need expiry tracking per customer and a way to ask their admin before it lapses.
Webhooks are how a headless agent learns that something happened. You create one with POST /spi/v3/subscriptions, a target URL, and one event. Workable lists candidate_created, candidate_moved, candidate_deleted, job_deleted, employee_created, employee_updated, employee_published, onboarding_completed, and timeoff_updated. Four properties shape the handler:
Use Workable MCP when:
Use the Workable API when:
Both paths hand you a Workable credential. Neither hands you a vault. A recruiting product serving 80 customer companies holds 80 account tokens on the API path, each generated by an admin, each able to read every candidate in that account, each with its own expiry date between 30 days and 2 years away. Add the webhook signing key, which is itself a token, and a careful setup holds 160. Each must be stored encrypted, kept out of logs and LLM context, mapped to exactly one subdomain, tracked against its expiry, and deleted when the customer churns. Each also needs a member map: 80 customers with 12 recruiters and hiring managers each is 960 member_id mappings that decide who gets credit, and blame, for every write.
The MCP path changes the shape, not the problem. Those 960 people each hold an OAuth session in a chat client, which Workable scopes correctly and you cannot list, audit, or revoke centrally from your product. The tempting shortcut on the API path is one token with every scope ticked. Fewer decisions, larger blast radius: that token can read confidential requisitions, employee salaries, and time off records for the whole company, and every recruiter's request runs with it.
Scalekit's workable connector stores each customer's Workable access token in the token vault and injects it into every call, so the MCP vs API decision doesn't change your auth infrastructure. Your agent passes an identifier; credentials never touch the agent runtime or the LLM context.
Recommended reading: OAuth vs API keys for AI agents
Scalekit's workable connector is an API-path connector built by Scalekit with 66 tools: 40 read-only, 26 write, and none destructive. It covers jobs, stages, questions, members, and recruiters; candidates, activities, files, comments, ratings, tags, custom attributes, copies, and relocations; offers; requisitions and their custom attributes; departments, legal entities, and work schedules; events; employees, fields, documents, and the org chart; time off; time tracking; and review templates. The core set for a pipeline assistant:
The connector authenticates with a Workable access token. There is no OAuth consent screen and no Scalekit-managed Workable app.
In the Scalekit dashboard, go to AgentKit > Connections and create a Workable connection. The name you give it is the connection_name your code passes, and the string must match the dashboard exactly. This is the most common integration error. Copy SCALEKIT_ENVIRONMENT_URL, SCALEKIT_CLIENT_ID, and SCALEKIT_CLIENT_SECRET from Developers > API Credentials into .env. See the connector docs.
Plan who generates the token at each customer, because only a Workable admin can. Ask for the narrowest scopes your agent needs: for the examples below, r_jobs (which also covers members and stages), r_candidates, and w_comments, with w_candidates only if the agent moves or tags candidates. Pick an expiry your customer success team can track; 1 year is a reasonable default.
get_or_create_connected_account returns the connected account for an identifier. If it is not ACTIVE, get_authorization_link returns a link to Scalekit's Hosted Connect page, where the customer's Workable admin enters the access token instead of approving an OAuth screen. Scalekit encrypts and stores it; your code never receives the token. The identifier here is your ID for the customer company, because an account token belongs to the account, not to one recruiter.
The first call after connecting does double duty. workable_members_list filtered by email confirms the token works against the right account and resolves the signed-in recruiter to their Workable member_id, which every write needs.
Store member_id against your user record. If the recruiter is deactivated in Workable, this lookup fails, and the agent should stop acting for them.
This is not a catalog load. The agent asks for the tools this customer's connected account is authorized to call, then narrows them to the seven a pipeline assistant needs. Because an account token reaches the whole account, this list is where the agent's reach becomes smaller than the token's. workable_candidate_disqualify, workable_candidate_tags_update, workable_employee_update, and workable_requisition_approve never reach the model, so it cannot reject a candidate or wipe their tags while answering a question about stage times. The one write it keeps, workable_candidate_comment_create, is additive and visible on the candidate's timeline.
The loop runs until the model stops requesting tools. Every call runs with this customer's token. The loop overwrites member_id on every tool call that accepts one, so the model can never choose whose identity a comment is posted under, whatever the prompt says. The system prompt carries what trips models up on this API: per-job stage slugs, paging.next cursors, and the 10-request window.
For pipelines, skip the model. execute_tool runs one tool with a fixed input and returns data plus an execution_id you can log. This handler runs when Workable delivers candidate_created to a per-customer URL such as /hooks/workable/cust_northwind/candidate_created, which also satisfies Workable's unique-target rule. It verifies X-Workable-Signature, re-reads the candidate because the payload is current state rather than event state, checks for earlier applications with the same email, merges a returning-applicant tag into the existing tags because workable_candidate_tags_update replaces the whole list, and posts a note visible to recruiters and admins. Writes are attributed to a dedicated integration member each customer creates in Workable, so the timeline shows the agent, not a random recruiter.
Workable replays any delivery that doesn't get a 200, so the tag check and a note keyed on the candidate keep repeats harmless. Workable documents the HMAC algorithm but not the encoding; the handler compares lowercase hex, which is what third-party integrations report, so log the first mismatch per customer rather than silently dropping it.
Workable documents no retry schedule, so pair the handler with reconciliation. workable_candidates_list takes updated_after and pages with since_id, and the loop below stays under the account-token limit by spacing calls one second apart.
The 26-hour window overlaps the previous daily run by two hours, so a candidate updated during a slow job isn't lost. Compare the IDs against what your webhook handler processed and run the handler for the difference.
Webhook subscriptions are a one-time setup per customer, and they belong in your own code. Because the subscribing token becomes the signing key, ask each customer's admin for a second token with only r_candidates, use it to create the subscriptions, and store it separately from the token in the Scalekit vault. A leaked signing token then reads candidates; it can't move, tag, or comment on them. For other authenticated calls the prebuilt tools don't cover, Scalekit custom connectors apply.
Store each subscription ID per customer, so offboarding can delete the subscriptions before the customer revokes the token.
A recruiting agent rarely stops at Workable. It finds stale candidates, then pings the hiring team in Slack. Load all 66 workable tools and the model holds workable_candidate_disqualify, workable_candidate_tags_update, workable_employee_update, and workable_requisition_approve while answering "who's waiting on feedback." At roughly 200 tokens each, 66 tools is about 13,200 tokens of definitions before the agent does any work, and Workable's own MCP server adds about 18,800 for its 94. A model choosing among workable_candidate_move, workable_candidate_relocate, and workable_candidate_copy picks the wrong one more often than a model holding only the one it needs, and two of the three change which job a candidate belongs to. The fix is not better prompting. It is surface reduction. A Scalekit virtual MCP server declares exactly which tools an agent role can see across connections, and session tokens keep each run bound to one identifier's connected accounts. Docs: set up a virtual MCP server.
One server definition serves every customer. Before each run, check that the identifier's accounts are active and mint a short-lived session token scoped to them. Any MCP client that speaks Streamable HTTP can connect; this example uses langchain-mcp-adapters (pip install langchain-mcp-adapters) and passes the token as a Bearer header.
The agent sees five tools instead of 66 plus everything Slack exposes, and none of them writes to Workable. The endpoint is static; the identity is per customer. Unlike Workable's own MCP server, this endpoint can carry tools Workable MCP doesn't have, such as workable_employee_create for the one onboarding role that should hold it, and leave them out of every other role. It also runs on a schedule with no one signed in, which Workable's member-scoped OAuth sessions can't.
Every execute_tool call returns an execution_id, and every execution is attributed to a connected account, which maps to one customer company. When a recruiting lead asks which agent run tagged 40 candidates as returning applicants overnight, or who commented "flagged as stale" on a candidate their CEO referred, the answer is a lookup, not an investigation.
Workable adds a second layer that you control. On the API path, the member_id you pass is what Workable's activity stream shows as the actor. Pass a dedicated integration member for webhook-driven writes and the signed-in recruiter's member for writes they asked for, and workable_candidate_activities_list tells the same story as your execution log. Pass whatever the model produced and Workable's own record becomes fiction. On the MCP path, every action is the signed-in member's, which is accurate, but nothing outside that chat client knows which agent session took it. A single account token shared by a whole customer collapses every recruiter into one credential; the member_id is the only thing that separates them, and only if your code sets it. Shared credentials are a single-user solution. They do not survive a second user.
Recommended reading: audit trails for agent auth
If your agent is a recruiter's or hiring manager's assistant inside Claude, ChatGPT, or Cursor, Workable's official MCP server is a strong fit: it is GA, broad, and enforces each member's role and job assignments without any work on your side. If your agent reacts to new applicants, runs scheduled digests, writes employee records, or serves many customer companies from your own product, build on the Workable API, where you choose the token scopes, the tool surface, and the member_id on every write, and where the 10-request window and the signing-key-is-a-token rule become your design constraints. Either way, you hold an admin-generated Workable credential per customer that reaches every candidate in the account, and that's what needs production-grade infrastructure.
Yes. Workable hosts an MCP server that went generally available on May 13, 2026 with 38 tools on every plan and now lists 94, covering jobs, candidates, offers, requisitions, members, employees, time off and performance reviews. It authenticates each member with OAuth and runs every call as that member, limited to their role and job assignments.
Self-serve access uses an account token that only an admin can generate, with scopes such as read jobs or write candidates and an expiry between 30 days and 2 years. OAuth and partner tokens exist but are limited to approved Workable partners. An account token reaches every candidate in the account, not one recruiter's jobs.
Moves, disqualifications and comments made with an account token require a member, which Workable records as the actor, and on HR endpoints that member's access level filters the result. Whoever controls that field controls whose identity the agent borrows, so in a multi-user agent your code must set it, never the model.
The API delivers signed webhooks for new and moved candidates, creates and updates employee records, attaches employee documents and runs headless on a schedule. The MCP server only acts inside a conversation, and its employee tools are read and search only. Offer approval through the API needs a user-level token, which self-serve account tokens are not.
Account tokens are limited to 10 requests per 10 seconds, and OAuth and partner tokens to 50, with rate-limit headers on every response and a 429 past the limit. The budget is shared by every workload on that customer's token, so an agent, a nightly sync and a reconciliation job all draw from the same window.
Each customer's Workable admin enters an access token once on a hosted page, and Scalekit stores it in a vault and injects it into every call, so the agent never sees it. The connector exposes 66 tools, 40 read and 26 write, which you narrow per agent role and serve as LangChain tools or through a virtual MCP server.
Browse the Scalekit Workable connector and the Workable connector docs with the full tool list. See Scalekit pricing, or talk to us.