MCP & REST API
Trackly MCP & REST API
Search 260K+ jobs across 5,500+ companies from an MCP client or your own REST integration.
Interactive playground: try any endpoint with your trk_ key.
Using Claude, ChatGPT, Codex, or another MCP client? The hosted MCP URL is https://mcp.usetrackly.app/api/mcp. The connector guide covers OAuth setup and the hosted tool catalog. Local setup is below; the CLI/MCP tool reference lists exact tool names. Hosted and local releases can differ: use the schemas your client discovers.
Base URL
https://closeai.mba/api/v1Five public endpoints: /jobs, /jobs/:id, /companies, /companies/search, /me (alias: /stats).
Authentication
Every request needs an API key passed as a Bearer token in the Authorization header.
Authorization: Bearer trk_xxxxxxxxxxxxxxxxxxxxGet your API key
- Open Settings > Developer (sign in first if you are not already).
- Name your key and click Create.
- Copy the
trk_key right away. It is shown only once.
For the CLI, run npx trackly-cli config --api-key trk_xxx or set TRACKLY_API_KEY=trk_xxx in your environment.
Quick Start
Start a local MCP server or use the REST examples below. For REST, replace trk_xxx with your own key.
Local MCP server
Requires Node.js 20.20 or later on the 20.x line, or 22.22 or later. Sign in, then configure a client that supports stdio MCP. Use the trackly-cli package name.
npx trackly-cli login
npx trackly-cli mcpIn a client that accepts an MCP JSON configuration:
{
"mcpServers": {
"trackly": {
"command": "npx",
"args": ["trackly-cli", "mcp"]
}
}
}Ask your client to call trackly_search_jobs, for example: "Find remote engineering roles and keep jobs where sponsorship is unknown." Use exclude_no to keep sponsored and unknown jobs. After updating the package, restart the MCP process/client and refresh tool discovery. Update separately installed skills or plugins through their documented update path or plugin manager.
Available filters vary by release and server. Inspect your client's current trackly_search_jobs schema and the CLI/MCP tool reference before using a filter. REST query parameters below do not imply availability on hosted or local MCP.
Google Apps Script
Sync jobs into a Google Sheet. Dedupes by job ID, safe to re-run.
/**
* Trackly -> Google Sheets job sync.
* Copy into a Google Sheet (Extensions -> Apps Script) and run syncJobs().
*
* Columns: Job ID | Title | Company | Company Domain | Location | Function | URL | Posted At
*/
const TRACKLY_API_KEY = 'trk_xxxxxxxxxxxxxxxxxxxx'; // Settings -> Developer in Trackly.
const SHEET_NAME = 'Trackly Jobs';
// Real v1 query params. Adjust to taste.
const QUERY_PARAMS = {
jobFunction: 'finance,partnerships',
locationFilter: 'us',
jobModality: 'full_time',
limit: 50,
sort: 'newest',
};
function syncJobs() {
const url = 'https://closeai.mba/api/v1/jobs?' + Object
.entries(QUERY_PARAMS)
.map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v))
.join('&');
const response = UrlFetchApp.fetch(url, {
method: 'get',
headers: { Authorization: 'Bearer ' + TRACKLY_API_KEY },
muteHttpExceptions: true,
});
if (response.getResponseCode() !== 200) {
throw new Error('Trackly API ' + response.getResponseCode() + ': ' + response.getContentText());
}
const { jobs } = JSON.parse(response.getContentText());
const sheet = getOrCreateSheet_();
const lastRow = sheet.getLastRow();
const existingIds = lastRow > 1
? new Set(
sheet.getRange(2, 1, lastRow - 1, 1)
.getValues()
.flat()
.map(String)
)
: new Set();
const newRows = jobs
.filter((job) => !existingIds.has(String(job.id)))
.map((job) => [
job.id,
job.title,
job.companyName, // flat alias - do NOT use job.company (that's a nested object)
job.company.domain, // nested object access when you want domain
job.location,
job.jobFunction,
job.jobUrl, // NOT job.url
job.postedAt, // NOT job.posted_at
]);
if (newRows.length) {
sheet.getRange(sheet.getLastRow() + 1, 1, newRows.length, newRows[0].length).setValues(newRows);
}
}
function getOrCreateSheet_() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(SHEET_NAME);
if (!sheet) {
sheet = ss.insertSheet(SHEET_NAME);
sheet.appendRow(['Job ID', 'Title', 'Company', 'Company Domain', 'Location', 'Function', 'URL', 'Posted At']);
sheet.setFrozenRows(1);
}
return sheet;
}Node.js
const response = await fetch('https://closeai.mba/api/v1/jobs?jobFunction=partnerships&limit=10', {
headers: { Authorization: `Bearer ${process.env.TRACKLY_API_KEY}` },
});
const { jobs, total } = await response.json();
for (const job of jobs) {
console.log(`${job.title} at ${job.companyName} - ${job.jobUrl}`);
console.log(` Company domain: ${job.company.domain}`);
}Python
import os
import requests
r = requests.get(
"https://closeai.mba/api/v1/jobs",
params={"jobFunction": "finance", "locationFilter": "us", "limit": 10},
headers={"Authorization": f"Bearer {os.environ['TRACKLY_API_KEY']}"},
)
r.raise_for_status()
for job in r.json()["jobs"]:
print(f'{job["title"]} at {job["companyName"]} - {job["jobUrl"]}')Rate Limits
All five public endpoints share a uniform limit of 10,000 requests per hour per user. Exceeding it returns a 429.
Each response includes X-RateLimit-Remaining and X-RateLimit-Reset headers.
Natural language search is experimental and not part of v1 - contact us if you need it.
Important semantics
Omitted discovery filters use your saved preferences
locationFilter=us, jobModality=full_time, and all 14 job functions. The saved posting window and salary floor are not inherited for explicit applied_confirmed, check_later, or not_interested views; explicit request values still apply. Pass every filter explicitly to make your script deterministic.job.company is a nested OBJECT, not a string
row.push(job.company) in a Google Sheet you'll see [object Object]. Use job.companyName for the flat string, or job.company.domain / job.company.fundingSeries to access nested fields./me (aliased as /stats) returns YOUR profile, not aggregate metrics
/me returns the authenticated user's profile, preferences, subscription, and feature flags. It is not a tracker-wide metrics endpoint. Both /api/v1/me and /api/v1/stats point at the same handler - prefer /me.Endpoints
/api/v1/jobsSearch and list job postings.
curl -H "Authorization: Bearer trk_xxx" \
"https://closeai.mba/api/v1/jobs?jobFunction=finance,partnerships&locationFilter=us&limit=2"Query parameters
| Param | Type | Notes |
|---|---|---|
jobFunction | string (comma-sep enum) | One or more of 14 canonical values: product, engineering, design, data, marketing, sales, partnerships, finance, strategy, operations, people, legal, support, other. Example: jobFunction=finance,partnerships. |
locationFilter | string (two modes) | Single-value: us | non_us | all | <region tag>. Comma-list: ONLY region tags (us/non_us/all are silently dropped if placed in a list). Region tags: europe, latam, middle_east, asia, africa, canada, oceania, remote, unknown. |
jobModality | full_time | internship | all | Employment type, independent of work arrangement. Use workArrangements for remote, hybrid, or in-person roles. |
search | string | Legacy keyword search. Does not guarantee exhaustive literal or full-description matches. Use search, not keywords. |
status | enum | Filters by the authenticated user's application pipeline state: new | check_later | applied_confirmed | not_interested | all. Not a job-posting status. |
sort | newest | match | Default: newest. Match sorting requires a resume. |
limit | integer | Default 50, max 100. MCP pagination defaults are separate; inspect the discovered tool schema. |
offset | integer | Pagination offset. |
region | string (comma-sep region tags) | Comma-separated tags: us, europe, latam, middle_east, asia, africa, canada, oceania, remote, unknown. Takes priority over locationFilter. Example: region=us,canada. |
usStates | string (comma-sep) | Two-letter US state codes plus DC, PR, and REMOTE. Example: usStates=NY,CA,REMOTE. For work arrangement independent of geography, use workArrangements. |
caProvinces | string (comma-sep) | Canadian province/territory codes: AB, BC, MB, NB, NL, NS, NT, NU, ON, PE, QC, SK, YT, plus REMOTE. Example: caProvinces=ON,BC,REMOTE. |
internshipLevels | string (comma-sep) | undergraduate | graduate | mba | not_specified. Applies to the internship subset of jobModality=internship or all; full-time roles are unaffected. |
workArrangements | string (comma-sep enum) | remote | hybrid | in_person | unspecified. Multiple values use OR semantics, independently of geography and employment type. |
sponsorship | all | exclude_no | only_yes | all does not filter. exclude_no keeps sponsored AND unknown jobs; only_yes keeps explicitly sponsored jobs. Filtering requires explicit status=new; omitted or other status ignores sponsorship. |
postedWithinDays | 0 | 1 | 3 | 7 | 14 | 30 | Restrict results to the selected posting window. Omitted uses your saved window when status is omitted, new, or all. Pipeline views (applied_confirmed, check_later, not_interested) do not inherit it; explicit values still apply. 0 disables the window. |
salaryFloorUsd | integer (0–1000000) | Annual USD salary floor. Excludes comparable listed annual-USD minimums below the floor; unknown, hourly, and non-USD salaries remain visible. 0 disables the floor. Omitted uses your saved floor when status is omitted, new, or all. Pipeline views (applied_confirmed, check_later, not_interested) do not inherit it; explicit values still apply. |
since | ISO 8601 timestamp | Incremental sync by when Trackly first saw a job, not its posting date. Must be within the past 90 days and cannot be in the future. Other filters remain active unless explicitly overridden; use postedWithinDays=0 and salaryFloorUsd=0 to disable those filters for sync. |
companyId | integer | Filter to a single company by ID. |
favoriteCompaniesOnly | boolean | Limits results to the caller's favorited companies. |
Response envelope
| Field | Type | Notes |
|---|---|---|
success | boolean | Always true on 200 responses. |
jobs | Job[] | Array of job objects (see schema below). |
total | number | Total jobs matching the filter (across all pages). |
hasMore | boolean | True if more jobs exist past this page. |
autoApplyDevEnabled | boolean | User-level auto-apply dev flag. |
servedFromCache | boolean | True if served from server-side cache. |
dataFreshnessMs | number | Cache age in ms. 0 = fresh from DB. |
pagination | object | { total, limit, offset, hasMore }. |
Job object (top-level fields)
| Field | Type | Notes |
|---|---|---|
id | number | Trackly job ID. |
externalId | string | ATS-native job ID. |
title | string | Job title. |
location | string | Free-form location string from the ATS. |
jobUrl | string (URL) | Apply URL. NOT "url". |
jobFunction | string | One of the 14 canonical function values. |
postedAt | string (ISO 8601) | When the company posted the job. |
firstSeenAt | string (ISO 8601) | When Trackly first scraped the job. |
isActive | boolean | True if the job is still live. |
isNew | boolean | True if posted within the last 24 hours. |
companyName | string | Convenience alias of company.name. Use this for flat spreadsheet output. |
companyId | number | Trackly company ID. |
companyDomain | string | Alias of company.domain. |
companyLogoUrl | string (URL) | Primary logo URL. |
companyLogoUrls | string[] | Ordered fallback logo URLs. |
company | object | Nested company object, NOT a string. See Company sub-table. |
atsSource | string | ATS vendor: ashby, greenhouse, lever, workday, etc. |
autoApplySupported | boolean | True if Trackly supports auto-apply on this ATS. |
isPM | boolean | Flagged as a product management role. |
isStrategyOps | boolean | Flagged as a strategy/operations role. |
isPartnership | boolean | Flagged as a partnerships role. SINGULAR in the response; the query-param is wantsPartnerships (plural, legacy). |
sponsorshipStatus | string | yes | no | unknown. |
sponsorshipEvidence | string | null | Quote or summary supporting the classification. |
sponsorshipClassifier | string | llm | reused | rule: how the classification was made. |
region | string | Single region tag: us | europe | latam | middle_east | asia | africa | canada | oceania | remote | unknown. |
seniorityLevel | string | null | junior | mid | senior | staff | director. |
salaryRange | string | null | Free-form range from the ATS when detected. |
visaSponsorship | string | null | Raw sponsorship note from the JD when detected. |
userStatus | string | null | The authenticated user's pipeline state for this job (new, check_later, applied_confirmed, not_interested). Null if unset. |
applyStartedAt | string | null | When the user started applying. |
appliedConfirmedAt | string | null | When the user confirmed the application. |
statusUpdatedAt | string | null | Last time the user changed status. |
timeToApplyMinutes | number | null | User-measured apply duration. |
matchScore | number | null | Per-user match score (0–100). |
matchReasons | string[] | Per-user match reason labels. |
matchLabel | string | null | Per-user match tier label. |
matchConfidence | string | null | Per-user confidence label. |
matchConfidenceReasons | string[] | Per-user confidence reasons. |
missingSkills | string[] | Per-user: skills the user's resume lacks. |
dimensionScores | object[] | Per-user: 7-dimension score breakdown. |
matchExplanation | string | null | Per-user: natural language match explanation. |
job.company (nested object)
| Field | Type | Notes |
|---|---|---|
id | number | Trackly company ID. |
name | string | Company name. |
domain | string | Primary domain (e.g. stripe.com). |
logoUrl | string (URL) | Primary logo URL. |
logoUrls | string[] | Ordered fallback logo URLs. |
companyStage | string | null | seed | early | growth | unicorn | decacorn | enterprise. |
fundingStage | string | null | PitchBook funding stage label. |
fundingSeries | string | null | Most recent round (e.g. Series C). |
valuationMillions | number | null | Last known valuation in USD millions. |
lastFinancingDate | string | null | ISO 8601 date of last round. |
description | string | null | One-paragraph company description. |
ycBatch | string | null | YC batch code (e.g. S09) if applicable. |
Example response
{
"success": true,
"jobs": [
{
"id": 211202955,
"externalId": "c019b11f-4fbb-46a2-bbad-338ba8f4bedb",
"title": "Agentic Finance Engineer",
"companyName": "Mercor",
"companyId": 1059,
"companyDomain": "mercor.com",
"companyLogoUrl": "https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fwww.mercor.com&size=128",
"companyLogoUrls": [
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fwww.mercor.com&size=128",
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fmercor.com&size=128",
"https://icons.duckduckgo.com/ip3/mercor.com.ico",
"https://ui-avatars.com/api/?name=Mercor&size=128&background=8b5cf6&color=fff&bold=true&format=png&length=2"
],
"location": "San Francisco",
"jobUrl": "https://jobs.ashbyhq.com/mercor/c019b11f-4fbb-46a2-bbad-338ba8f4bedb",
"atsSource": "ashby",
"autoApplySupported": false,
"isPM": false,
"isStrategyOps": false,
"isPartnership": false,
"jobFunction": "finance",
"postedAt": "2026-04-18T20:39:30.721Z",
"firstSeenAt": "2026-04-18T21:27:41.348Z",
"isNew": false,
"isActive": true,
"sponsorshipStatus": "unknown",
"region": "us",
"seniorityLevel": "mid",
"company": {
"id": 1059,
"name": "Mercor",
"domain": "mercor.com",
"logoUrl": "https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fwww.mercor.com&size=128",
"logoUrls": [
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fwww.mercor.com&size=128",
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fmercor.com&size=128",
"https://icons.duckduckgo.com/ip3/mercor.com.ico",
"https://ui-avatars.com/api/?name=Mercor&size=128&background=8b5cf6&color=fff&bold=true&format=png&length=2"
],
"companyStage": "decacorn",
"fundingStage": "Later Stage VC",
"fundingSeries": "Series C",
"valuationMillions": 10000,
"lastFinancingDate": "2026-02-04T00:00:00.000Z",
"description": "Developer of an artificial intelligence-powered hiring platform...",
"ycBatch": null
}
}
],
"total": 3,
"hasMore": true,
"autoApplyDevEnabled": false,
"servedFromCache": false,
"dataFreshnessMs": 0,
"pagination": { "total": 3, "limit": 2, "offset": 0, "hasMore": true }
}/api/v1/jobs/:idFetch a single job with the full description and (when available) structured JD fields.
curl -H "Authorization: Bearer trk_xxx" \
"https://closeai.mba/api/v1/jobs/211202955"The response uses the same shape as the list endpoint, plus the additional top-level fields below. The structured fields are flat siblings of title - there is no structuredJd wrapper object.
Additional detail fields
| Field | Type | Notes |
|---|---|---|
description | string | Plain-text full job description. |
descriptionHtml | string | HTML-formatted job description. |
minutesAgo | number | Minutes since postedAt. |
recommendations | string[] | Per-user: suggested actions to improve fit. |
quickWins | string[] | Per-user: quick resume tweaks. |
candidateFit | string | null | Per-user: narrative fit summary. |
skillsOverlap | object | null | Per-user: resume-vs-JD skill comparison. |
seniorityLevel | string | null | Optional (only when structured_jd is populated). Flat field, NOT nested under structuredJd. |
salaryMin | number | null | Optional. Flat field. |
salaryMax | number | null | Optional. Flat field. |
salaryCurrency | string | null | Optional. Flat field (e.g. USD). |
salaryPeriod | string | null | Optional. Flat field (year, hour, etc). |
structuredSkills | string[] | Optional. Required skills extracted from JD. |
structuredPreferredSkills | string[] | Optional. Nice-to-have skills. |
structuredBenefits | string[] | Optional. Benefits mentioned in JD. |
structuredTools | string[] | Optional. Tools/frameworks mentioned. |
structuredSponsorshipInfo | string | null | Optional. Extracted sponsorship info. |
Example response
{
"success": true,
"job": {
"id": 211202955,
"externalId": "c019b11f-4fbb-46a2-bbad-338ba8f4bedb",
"title": "Agentic Finance Engineer",
"location": "San Francisco",
"jobUrl": "https://jobs.ashbyhq.com/mercor/c019b11f-4fbb-46a2-bbad-338ba8f4bedb",
"description": "About Mercor\n\nMercor is defining the future of work...",
"descriptionHtml": "<h2><strong>About Mercor</strong></h2>...",
"isPM": false,
"isStrategyOps": false,
"isPartnership": false,
"jobFunction": "finance",
"postedAt": "2026-04-18T20:39:30.721Z",
"firstSeenAt": "2026-04-18T21:27:41.348Z",
"minutesAgo": 686,
"region": "us",
"seniorityLevel": "mid",
"salaryMin": null,
"salaryMax": null,
"salaryCurrency": null,
"salaryPeriod": null,
"structuredSkills": ["finance domain knowledge", "SQL", "Python"],
"structuredPreferredSkills": ["deploying AI agents", "LLM-powered tools"],
"structuredBenefits": [],
"structuredTools": [],
"structuredSponsorshipInfo": null,
"company": {
"id": 1059,
"name": "Mercor",
"domain": "mercor.com",
"atsType": "ashby",
"companyStage": "decacorn",
"fundingSeries": "Series C",
"valuationMillions": 10000
}
}
}/api/v1/companiesList monitored companies with per-function job counts.
curl -H "Authorization: Bearer trk_xxx" \
"https://closeai.mba/api/v1/companies?limit=50"Always pass limit - the response is large
functionCounts object plus funding metadata. An unbounded response with 5,566 companies can exceed 1 MB. Pass an explicit limit to keep payloads snappy.Query parameters
| Param | Type | Notes |
|---|---|---|
limit | integer | Optional; capped at 500. When omitted, returns all companies. |
offset | integer | Pagination offset. |
Response envelope
| Field | Type | Notes |
|---|---|---|
success | boolean | Always true on 2xx. |
companies | Company[] | See the Company object table below. |
count | number | Number of companies in this page. |
total | number | Total companies matching the filter (across all pages). |
servedFromCache | boolean | True if served from cache. |
dataFreshnessMs | number | Cache age in ms. 0 when fresh. |
Company object
| Field | Type | Notes |
|---|---|---|
id | number | Company ID. |
name | string | Company name. |
domain | string | Primary domain. |
logoUrl | string (URL) | Primary logo URL. |
logoUrls | string[] | Ordered fallback logo URLs (gstatic → ddg → ui-avatars terminator). |
atsType | string | ATS vendor identifier. |
industry | string | null | Classified industry tag. |
isFavorite | boolean | True if favorited by the authenticated user. |
pmJobCount | number | Active PM jobs at this company. |
totalJobCount | number | All active jobs. |
mbaJobCount | number | Active MBA-relevant jobs. |
functionCounts | object | { [function: string]: number }. 14-key breakdown across all canonical job functions. Large object. |
companyStage | string | null | seed | early | growth | unicorn | decacorn | enterprise. |
fundingStage | string | null | PitchBook funding stage label. |
fundingSeries | string | null | Most recent round. |
valuationMillions | number | null | USD millions. |
lastFinancingDate | string | null | ISO 8601 date. |
description | string | null | Company description. |
ycBatch | string | null | YC batch code. |
Example response
{
"success": true,
"companies": [
{
"id": 1,
"name": "Stripe",
"domain": "stripe.com",
"logoUrl": "https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fwww.stripe.com&size=128",
"logoUrls": [
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fwww.stripe.com&size=128",
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http%3A%2F%2Fstripe.com&size=128",
"https://icons.duckduckgo.com/ip3/stripe.com.ico",
"https://ui-avatars.com/api/?name=Stripe&size=128&background=8b5cf6&color=fff&bold=true&format=png&length=2"
],
"atsType": "greenhouse",
"industry": "fintech",
"isFavorite": false,
"pmJobCount": 13,
"totalJobCount": 227,
"mbaJobCount": 4,
"functionCounts": {
"product": 13, "engineering": 64, "design": 7, "data": 7,
"marketing": 16, "sales": 32, "partnerships": 4, "finance": 11,
"strategy": 10, "operations": 22, "people": 9, "legal": 3,
"support": 3, "other": 26
},
"companyStage": "enterprise",
"ycBatch": "S09"
}
],
"count": 50,
"servedFromCache": false,
"dataFreshnessMs": 0
}/api/v1/companies/searchSemantic company search by name, domain, or description.
curl -H "Authorization: Bearer trk_xxx" \
"https://closeai.mba/api/v1/companies/search?q=stripe"Query parameters
| Param | Type | Notes |
|---|---|---|
q | string | Search text. Required. Min 2 chars, max 200. |
limit | integer | Default 20, max 50. |
Response shape
Same companies[] array as /companies. Envelope fields:
| Field | Type | Notes |
|---|---|---|
success | boolean | Always true on 2xx. |
companies | Company[] | Same shape as /companies. |
count | number | Number of companies in this page. |
total | number | Total companies matching the search (across all pages). |
searchSource | string | sql_fallback | ... - indicates which search path served the query. |
servedFromCache | boolean | True if served from cache. |
dataFreshnessMs | number | Cache age in ms. 0 when fresh. |
Example response
{
"success": true,
"companies": [ /* same shape as /companies list */ ],
"count": 1,
"total": 1,
"searchSource": "sql_fallback",
"servedFromCache": false,
"dataFreshnessMs": 0
}/api/v1/mealias: /api/v1/statsThe authenticated user's profile, saved preferences, subscription, and feature flags.
curl -H "Authorization: Bearer trk_xxx" \
"https://closeai.mba/api/v1/me"user object
| Field | Type | Notes |
|---|---|---|
id | number | User ID. |
email | string | User email. |
name | string | Display name. |
picture | string (URL) | Avatar URL. |
autoApplyDevEnabled | boolean | Auto-apply dev flag. |
preferences | object | Saved job preferences (see sub-table). |
subscription | object | { status: string, expiresAt: string | null }. |
onboardingCompleted | boolean | True if onboarding finished. |
featureFlags | object | { networkingV1: boolean } (currently). |
user.preferences
| Field | Type | Notes |
|---|---|---|
wantsPM | boolean | User wants product management roles. |
wantsStrategyOps | boolean | User wants strategy/ops roles. |
wantsPartnerships | boolean | User wants partnerships roles. |
wantedJobFunctions | string[] | Up to 14 canonical function values the user wants to see. |
locationFilter | string | Saved location filter (same semantics as the query param). |
needsSponsorship | boolean | User needs visa sponsorship. |
jobModality | string | full_time | internship | all. |
experienceRange | any | null | Legacy experience-range object. |
experienceRanges | any | null | Newer multi-range object. |
internshipLevels | string[] | null | undergraduate/graduate/mba/not_specified. |
favoritesDailyDigest | boolean | Daily push digest (iPhone/Mac) of favorited companies; defaults to true. |
notificationsFavoritesOnly | boolean | Limit notifications to favorited companies. |
notificationFrequency | string | realtime | daily_digest | off. |
Example response
{
"success": true,
"user": {
"id": 1,
"email": "[email protected]",
"name": "Example User",
"picture": "https://example.com/avatar.png",
"autoApplyDevEnabled": false,
"preferences": {
"wantsPM": true,
"wantsStrategyOps": false,
"wantsPartnerships": false,
"wantedJobFunctions": ["product"],
"locationFilter": "us",
"needsSponsorship": false,
"jobModality": "full_time",
"experienceRange": null,
"experienceRanges": null,
"internshipLevels": null,
"favoritesDailyDigest": true,
"notificationsFavoritesOnly": false,
"notificationFrequency": "realtime"
},
"subscription": { "status": "none", "expiresAt": null },
"onboardingCompleted": true,
"featureFlags": { "networkingV1": false }
}
}Errors
Error responses use standard HTTP status codes and include a JSON body:
{
"error": "Invalid or revoked API key"
}| Code | Meaning |
|---|---|
| 400 | Invalid request - usually a bad enum value on status or jobFunction, or a q shorter than 2 chars on /companies/search. |
| 401 | Missing, invalid, or revoked API key. |
| 429 | Rate limit exceeded (10,000 requests/hour). |
| 500 | Internal server error. |