Partner API
Build on Tahoe
A read-only HTTP API over the jobs, applications, candidates and pipelines in a Tahoe workspace, a change feed and webhooks to stay current, and Sign in with Tahoe so your users can authenticate with the account they already have.
Quickstart
Mint a key and make your first authenticated call in about five minutes.
Authentication
Bearer keys, scopes, environments, IP allowlists and workspace reach.
Conventions
Handles, pagination, timestamps, and how a withheld field is reported.
Errors
Every code the API can return, and which ones are worth retrying.
Change feed
38 event types, cursored, so a nightly full re-read is never necessary.
Agent prompt
A ready-made system prompt for building against this API with an LLM.
Base URL and version
One base URL for every environment. There is no separate sandbox host — a test key and a live key read the same workspace through the same path, and the prefix on the secret is what tells them apart in a log.
https://tahoe.workonward.com/api/partner/v1Every response carries the API version in Tahoe-Partner-Api-Version, and GET /ping reports it without authentication. The version is a date, and it changes only for a breaking change — new fields, new endpoints and new event types are added without one.
Three things to know before you start
It is read-only, and that is a design decision
Every data endpoint is a GET. The two POSTs that exist — /people/resolve:batch and /pool/search — are reads with bodies too large for a query string. Nothing you can call through this API creates, edits or deletes anything in a Tahoe workspace.
So a Tahoe integration cannot corrupt a customer’s hiring data, and a leaked key is a confidentiality incident rather than an integrity one. Write access, if it ever exists, will be a separate surface with its own scopes and its own review.
Personal data is metered and audited, not merely scoped
Emails, phone numbers and resumes sit behind their own scopes, and reading one writes a row naming the key, the record and the field. There is a daily budget on personal-data reads that is separate from the request rate limit: you can page jobs all day and still be stopped from harvesting phone numbers.
The API also never sells you data a workspace has not already paid to reveal. A contact field that has never been unlocked is reported as withheld, with a reason — it is not silently null, and it is not available at a cheaper price here than in the product.
Nothing is exposed that a recruiter could not already see
The API is a view onto one workspace’s own data. It is not a back door into Tahoe’s whole corpus, another tenant’s pipeline, or the content of a phone screening. What is never exposed lists the categories that have no representation in this API at all.
The surface, at a glance
| Area | What you get | Scopes |
|---|---|---|
| Jobs | Requisitions, structured sections, application-form schema, pipeline stages, pre-screening questions | jobs:read |
| Applications | Applications, stage and status, form answers, match scores, stage history, resume metadata and downloads | applications:read |
| Applicants | The people who applied, their applications, their resumes, their contact information | applicants:read |
| Sourced profiles | Candidates the workspace sourced, revealed contact information, attachments, pipeline membership | sourced_profiles:read |
| Shared pool | Tahoe's pool of public professional profiles, and a search over it that spends nothing | pool:read |
| People | Resolve your own records to a Tahoe person by email or LinkedIn URL, then read across every profile behind them | people:resolve |
| Projects and lists | Projects, candidate lists, members and their stage | lists:read |
| Analytics | Aggregate hiring-funnel counts | analytics:read |
| Events | A cursored change feed, erasure notices, and webhook delivery status | events:read |
| Sign in with Tahoe | Standard OIDC authorization-code flow with PKCE | no API key |
Who can create a key
API keys are minted from Settings → Developer inside Tahoe, and only by users whose account email is on the workonward.com, workonward.org or dhdgroup.net domains. Everyone else sees the tab explain why it is unavailable rather than a button that fails.
Your first call
GET /me reports exactly what the credential in your hand can do — its scopes, which workspaces it can reach, whether it must name one, and its current limits. It is the fastest way to tell a configuration problem from a code problem.
curl https://tahoe.workonward.com/api/partner/v1/me \
-H "Authorization: Bearer $TAHOE_API_KEY"{
"object": "credential",
"id": "pk_9tRc4mQx7Lb2",
"name": "WorkOnward HRIS sync",
"environment": "live",
"scopes": ["applications:read", "jobs:read", "workspaces:read"],
"scope_descriptions": {
"applications:read": "Applications, their stage and status, and match scores.",
"jobs:read": "Job postings, their content, application forms and pipeline stages.",
"workspaces:read": "Workspace name and creation date."
},
"workspace_scope": "single",
"workspace_ids": ["wsp_4Kd8sPm2Qx7L"],
"workspace_id_required": false,
"rate_limits": {
"general_per_minute": 600,
"expensive_per_minute": 60,
"download_per_minute": 30,
"personal_data_reads_per_day": 5000,
"personal_data_reads_used_today": 128,
"max_page_size": 100,
"default_page_size": 25,
"max_result_window": 10000
},
"created_at": "2026-09-09T10:14:22.510Z",
"expires_at": "2026-12-08T10:14:22.510Z",
"api_version": "2026-09-09"
}Getting help
Every error response carries a request_id. Quote it — with it a support request is a lookup, and without it, a guess.
