First-party app
Lever

Lever

Lever: read and move candidates through the hiring pipeline, manage postings, notes and archive state.

stable Human ResourcesProductivity

About

Lever ships in the w6w first-party pack. It declares 12 actions, 2 health checks, and the host runs its code in a sandbox that never sees the credential.

App id
io.w6w.lever
Version
0.1.1
Author
w6w
Licence
MIT
Categories
Human Resources · Productivity

Overview

Lever runs a company’s hiring pipeline, and this app moves and reads candidates through it: list and inspect opportunities (a candidate’s application to one specific posting), move somebody to a new stage, archive or reopen an application, write notes, and see offers, postings and pipeline stages.

A few of Lever’s own conventions carry through directly. A person is a contact, separate from each of their applications, so someone who applied three times is one contact with three opportunities. Listing opportunities defaults to including confidential candidates as well as ordinary ones, since Lever’s own API silently excludes them otherwise. And every write is attributed to a specific user, so notes and stage moves show up as made by a real person rather than by whichever credential happens to be connected.

This app covers the everyday recruiting loop — reviewing and moving candidates, writing notes, checking what’s been offered — rather than posting management or account administration, and it surfaces Lever’s own stage and archive-reason names so a workflow can resolve them without guessing at ids that differ per account.

Build with Lever

Three routes to the same 12 actions. The Workflow tab is generated from Lever's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.

List archive reasons

archive-reason-list

Why candidates get closed out, and — the part that matters — which reasons count as a HIRE. `opportunity-archive` behaves very differently depending on the reason, and nothing in that call distinguishes them.

Add a note

note-add

Write on a candidate's profile, which is where recruiters actually look. Notes are PERMANENT — the API can delete but not edit — visible to everyone with access to the candidate, and discoverable in a data-subject request.

List notes

note-list

What has been written about a candidate — the record a data-subject request covers. DELETED notes are still returned with a timestamp, and restricted notes appear only if the key can see them, so an empty result and a filtered one look identical.

List offers

offer-list

What has been offered to a candidate and where it got to. `signed` is acceptance; `approved` is only the INTERNAL approval chain, which is a different thing. Offer fields are that account's own form and usually include compensation.

Archive or unarchive an opportunity

opportunity-archive

Close a candidate out, mark them HIRED, or reopen them — one endpoint, and the REASON decides which. A hire reason with a requisition increments that requisition's hire count. An empty reason unarchives.

Create an opportunity

opportunity-create

Add a candidate. Lever DEDUPES on email and never creates a second person — and the existing contact's data wins, so a create carrying a corrected phone number silently keeps the old one. Requires `performAs`, which decides who the audit trail credits.

Get an opportunity

opportunity-get

One application with the person behind it. Nearly every field is an ID until `expand` inlines it, and doing that in one request matters because Lever rate-limits with no header to pace against. Flags an ANONYMIZED contact, which has no name or email by design.

List opportunities

opportunity-list

The pipeline. Note Lever's `confidentiality` defaults to NON-CONFIDENTIAL, so the obvious call silently omits records — this defaults to `all` and reports what it used. Returns the deduplicated CONTACT ids, since one person can hold several opportunities.

Move an opportunity to a stage

opportunity-stage-set

Move a candidate through the pipeline — a visible act that notifies people and triggers Lever's own automations. Stage IDS are per account and are not names, so looking them up with `stage-list` at run time is what survives a pipeline being rebuilt.

List postings

posting-list

The jobs. `state` distinguishes PUBLISHED from INTERNAL — both are open roles, and which one is a hiring decision. Defaults confidentiality to `all`, since Lever's own default quietly omits confidential postings.

List stages

stage-list

The pipeline's stages with their IDS — which every write takes and which differ between accounts, so resolving by name at run time is what survives a rebuild. Reports duplicate names rather than collapsing them.

List users

user-list

Who works here — and where every write action's `performAs` id comes from, since Lever attributes actions to people. Flags DEACTIVATED users, whose ids still work: a workflow pointed at one keeps signing notes as somebody who left.

A workflow step names the app and the action, and the editor fills in the connection when you pick one. This is the Step shape from the workflow spec, carrying Lever's real ids.

{
  "manifestVersion": "2",
  "name": "lever-example",
  "steps": [
    {
      "id": "note-add",
      "uses": {
        "app": "io.w6w.lever",
        "action": "note-add",
        "connection": "conn_YOUR_CONNECTION_ID"
      },
      "with": {
        "opportunityId": "<opportunityId>",
        "value": "<value>",
        "performAs": "<performAs>"
      }
    }
  ]
}

Here are some of the things you can do

  • Add a note

    perform
    note-add
  • List notes

    read
    note-list
  • List offers

    read
    offer-list
  • Create an opportunity

    perform
    opportunity-create
  • Get an opportunity

    read
    opportunity-get

+7 more actions available

Every app-specific value here is a blank you have to fill in. An app action is reached through the connection that authenticates it, so the address is a connection id, not the app id — and connections belong to your account, so a public page cannot know yours. Create one for Lever, then fill in the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the parameters that action declares. The call itself is real — the shape is transcribed from the studio's own snippet builder, which prints the same kind of blanks — but nothing in it is specific to Lever. The Workflow tab is where this app's real ids are.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { W6wClient, isActionRun } from "@w6w/sdk";

// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();

const envelope = await client.run({
  urn: "conn_YOUR_CONNECTION_ID",
  action: "note-add",
  payload: {
    opportunityId: "<value>",
    value: "<value>",
    performAs: "<value>",
    // secret: "<value>",
    // notifyFollowers: "<value>",
    // createdAt: "<value>",
  },
});

if (isActionRun(envelope)) console.log(envelope.value);
Install the CLI
npm install -g @w6w/cli
CLI
w6w run conn_YOUR_CONNECTION_ID --action note-add --payload '{"opportunityId":"<value>","value":"<value>","performAs":"<value>"}'

Give an AI agent Lever — without giving it Lever's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.

One tool call
{
  "name": "w6w_invoke",
  "arguments": {
    "ref": "app:io.w6w.lever#note-add",
    "input": {
      "opportunityId": "<opportunityId>",
      "value": "<value>",
      "performAs": "<performAs>"
    }
  }
}

Every tool names its target with a single ref. The app: form above doesn't name a connection at all — the host resolves which of the caller's Lever connections to sign with, and refuses rather than guesses when the answer is ambiguous.

What the agent gets

Credentials it can't read

The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.

A tool surface scoped to the caller

Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.

A durable workflow in one call

Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.

Health-aware discovery

Lever's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.

The MCP surface is part of the hosted platform. Lever itself is MIT, and the runtime that executes it is source-available (FSL).

Request MCP access

Health checks

Lever declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

Lever status

Reads Lever's Statuspage for the DATA CENTRE this connection names — every component appears twice, once per data centre, so a name match alone reports another region's incident. Weights the API component, and reports the product separately.

quota

Rate-limit headroom

Declared unavailable — Lever rate-limits and publishes no header for the budget, the window or what is left, so exponential backoff is the only strategy. What actually shapes an integration is the OPAQUE PAGINATION CURSOR, which cannot be parallelised.