interface components {
schemas: {
AcceptCompanyMemberInviteBody: {
token: string;
};
AccessCheckoutBody: {
/**
* @description The offer tier to purchase (from `GET /paywall/offers/enabled`).
* @enum {string}
*/
offerKey: "daily" | "weekly" | "monthly" | "quarterly" | "yearly" | "lifetime";
/** @description Relative path Stripe returns the buyer to on completion; `session_id` is appended. */
returnPath: string;
/** @enum {string} */
colorMode: "light" | "dark";
};
AccessCheckoutSession: {
/** @enum {string} */
object: "checkout_session";
sessionId: string;
/** @description The Checkout Session client secret to mount the embedded form. */
clientSecret: string;
/** @description The board’s connected Stripe account to initialise Stripe.js with. */
stripeAccountId: string;
/** @description The platform Stripe publishable key for `loadStripe`. */
publishableKey: string;
/**
* @description `recurring` grants get a manage-subscription portal; `lifetime` do not.
* @enum {string}
*/
offerType: "recurring" | "lifetime";
};
AccessCheckoutSessionState: {
/** @enum {string} */
object: "checkout_session_state";
/** @enum {string} */
status: "open" | "complete" | "expired";
clientSecret: string | null;
};
AccessGrant: {
/** @enum {string} */
object: "access_grant";
hasAccess: boolean;
/** @enum {string|null} */
status: "active" | "past_due" | "unpaid" | "incomplete" | "incomplete_expired" | "canceled" | "pending" | null;
/** @enum {string|null} */
offerType: "recurring" | "lifetime" | null;
offerKey: string | null;
currentPeriodEnd: string | null;
cancelAtPeriodEnd: boolean;
};
AccessPortalBody: {
/** @description Relative path Stripe returns the buyer to; defaults to the board root. */
returnPath?: string;
};
AccessPortalSession: {
/** @enum {string} */
object: "portal_session";
/** Format: uri */
url: string;
};
AddApplicantNoteBody: {
/** @description The note text. */
body: string;
};
AddSourcedCandidateBody: {
job: string;
candidateBoardUserId: string;
};
Alert: {
/** @description Job-alert preference ID. Also the path key. */
id: string;
/** @enum {string} */
object: "alert";
label: string | null;
/** @enum {string} */
frequency: "weekly";
isActive: boolean;
filters: {
jobFunctions: string[];
seniorityLevels: string[];
remoteOptions: string[];
placeIds: string[];
salaryMin: number | null;
salaryMax: number | null;
salaryCurrency: string | null;
};
/**
* Format: date-time
* @description When this alert last dispatched a digest, or null.
*/
lastSentAt: string | null;
};
AlertBody: {
label?: string;
/** @enum {string} */
frequency: "weekly";
jobFunctions?: string[];
seniorityLevels?: string[];
remoteOptions?: string[];
placeIds?: string[];
salaryMin?: number | null;
salaryMax?: number | null;
salaryCurrency?: string | null;
};
Application: {
/** @description Application ID. Also the `:applicationId` path key. */
id: string;
/** @enum {string} */
object: "application";
/**
* @description Coarse candidate-facing status derived from the employer pipeline stage.
* @enum {string}
*/
status: "applied" | "interviewing" | "negotiation" | "hired" | "archived";
/** Format: date-time */
appliedAt: string;
/** Format: date-time */
updatedAt: string;
coverNote: string | null;
candidateName: string | null;
candidateEmail: string | null;
candidateLocation: string | null;
candidateHeadline: string | null;
resumeFilename: string | null;
job: {
id: string;
title: string;
slug: string | null;
companySlug: string | null;
companyName: string | null;
} | null;
};
ApplyApprovalPlan: {
/** @enum {string} */
object: "apply_approval_plan";
/** @enum {string} */
kind: "not_required";
} | {
/** @enum {string} */
object: "apply_approval_plan";
/** @enum {string} */
kind: "approval_required";
/** Format: uri */
approvalUrl: string;
/** Format: date-time */
expiresAt: string;
};
ApplyBody: {
name?: string;
/** Format: email */
email?: string;
coverNote?: string;
/** @description Opaque native country-approval receipt returned by the browser-direct Apply gateway. */
approvalReceipt?: string;
/** @description Server-owned board session key that prepared the country approval. */
approvalSessionKey?: string;
};
ApplyIntent: {
/** @description Opaque one-time Apply intent token. */
id: string;
/** @enum {string} */
object: "apply_intent";
/** Format: uri */
gatewayUrl: string;
/** Format: date-time */
expiresAt: string;
};
Block: {
/** @enum {string} */
object: "block";
/** @enum {boolean} */
blocked: true;
};
BlockStatus: {
/** @enum {string} */
object: "block_status";
blocked: boolean;
};
BlockUserBody: {
boardUserId: string;
};
BlockedUser: {
id: string;
/** @enum {string} */
object: "blocked_user";
boardUserId: string;
displayName: string;
avatarUrl: string | null;
/** Format: date-time */
createdAt: string;
};
BoardAccessGrant: {
/** @enum {string} */
object: "board_access_grant";
/** @description The board-access grant. Send it as the `X-Board-Access` header on subsequent content reads to pass the password wall. */
token: string;
};
BoardAuthConsumeMagicLinkBody: {
token: string;
};
BoardAuthForgotPasswordBody: {
/** Format: email */
email: string;
};
BoardAuthLoginBody: {
/** Format: email */
email: string;
password: string;
};
BoardAuthLogoutBody: {
refreshToken: string;
};
BoardAuthOAuthAuthorizationUrl: {
/** @enum {string} */
object: "oauth_authorization_url";
/** @enum {string} */
provider: "google" | "linkedin";
/** Format: uri */
authorizeUrl: string;
};
BoardAuthOAuthExchangeBody: {
token: string;
};
BoardAuthRefreshBody: {
refreshToken: string;
};
BoardAuthRegisterBody: {
/**
* @description Which role profile to create on the board.
* @enum {string}
*/
role: "candidate" | "employer";
/**
* @description Registration method. Only `emailpass` is supported.
* @enum {string}
*/
method: "emailpass";
/** Format: email */
email: string;
/** @description Minimum 8 characters. */
password: string;
displayName: string;
/** @description True only when the person ticked a marketing checkbox your UI displayed with its disclosure wording. Omit when no checkbox was shown; false and absent both record nothing. */
marketingConsent?: boolean;
};
BoardAuthRequestMagicLinkBody: {
/** Format: email */
email: string;
/** @description Optional same-origin path to carry through the email link. */
returnTo?: string;
/**
* @description Pass `sign_in` from a sign-in form: an unknown email returns 404 `board_auth_account_not_found` and nothing is minted or sent; existing users are unchanged. Omit it for today’s behaviour (existing users get a sign-in token; unknown emails get a candidate sign-up token when candidate registration is enabled).
* @enum {string}
*/
intent?: "sign_in";
};
BoardAuthResetPasswordBody: {
token: string;
/** @description Minimum 8 characters. */
password: string;
};
BoardAuthSession: {
/** @enum {string} */
object: "board_auth_session";
/** @description Short-lived JWT (1 hour). Send as `Authorization: Bearer`. */
accessToken: string;
/** @description Opaque single-use refresh token (30 days). Each refresh returns a replacement; a reused token is rejected. */
refreshToken: string;
/** @description Access-token expiry, epoch milliseconds. */
expiresAt: number;
boardUser: components["schemas"]["BoardUser"];
/** @description Present on OAuth exchange and magic-link consume. True when this exchange created the board user account (candidate or employer); false when it authenticated an existing account. */
isNewUser?: boolean;
};
BoardAuthVerifyEmailBody: {
token: string;
};
BoardSeo: {
/** @enum {string} */
object: "board_seo";
/** @description Verbatim `ads.txt` content, or `null` when not configured. */
adsTxt: string | null;
/** @description IndexNow key-file content, or `null` when not configured. */
indexNowKey: string | null;
/** @description Google site-verification token for the `` tag, or `null`. */
googleSiteVerification: string | null;
/**
* Format: uri
* @description The board's canonical base URL (honours a configured custom domain). Build `robots.txt`'s `Sitemap:` line (`${canonicalBase}/sitemap.xml`) and canonical links from it.
*/
canonicalBase: string;
/** @description Web-manifest name only. Theme color and icons left the surface in 4.0.0: applications own brand assets and presentation tokens. */
manifest: {
name: string;
};
};
BoardSitemap: {
/** @enum {string} */
object: "board_sitemap";
/** @description The buckets the board publishes, in the canonical bucket order. Empty buckets are omitted — exactly the set the hosted `/sitemap.xml` index lists. */
buckets: components["schemas"]["BoardSitemapBucketSummary"][];
};
BoardSitemapBucketSummary: {
/** @description Bucket name — pass it to `GET /boards/:identifier/sitemap/{bucket}` to read its entries. */
bucket: string;
/** @description Number of entries in the bucket. */
count: number;
/** @description ISO 8601 timestamp of the newest content in the bucket, when the board tracks one. */
lastModified?: string;
};
BoardUser: {
/** @description Board user ID. */
id: string;
/** @enum {string} */
object: "board_user";
/** @enum {string} */
role: "candidate" | "employer";
email: string;
displayName: string | null;
emailVerified: boolean;
/** @description Whether the account has a password credential. False for OAuth/magic-link-only accounts; frontends use it to offer change-password vs set-password (the set flow is POST /auth/forgot-password). */
hasPassword: boolean;
};
BulkMoveApplicantsBody: {
applicationIds: string[];
/** @description The target stage id. */
stageId: string;
};
BulkRejectApplicantsBody: {
applicationIds: string[];
};
CandidateAvatar: {
/** @enum {string} */
object: "candidate_avatar";
avatarUrl: string | null;
};
CandidateEducation: {
id: string;
/** @enum {string} */
object: "candidate_education";
institutionName: string;
institutionUrl: string | null;
degree: string | null;
fieldOfStudy: string | null;
grade: string | null;
activitiesAndSocieties: string | null;
startDate: string | null;
endDate: string | null;
description: string | null;
sortOrder: number;
};
CandidateExperience: {
id: string;
/** @enum {string} */
object: "candidate_experience";
title: string;
companyName: string;
companyUrl: string | null;
location: string | null;
employmentType: string | null;
locationType: string | null;
foundVia: string | null;
startDate: string;
endDate: string | null;
description: string | null;
sortOrder: number;
experienceSkills: string[];
};
CandidateLanguage: {
/** @enum {string} */
object: "candidate_language";
name: string;
proficiency: string;
};
CandidateProfile: {
id: string;
/** @enum {string} */
object: "candidate_profile";
displayName: string | null;
bio: string | null;
avatarUrl: string | null;
handle: string | null;
headline: string | null;
location: string | null;
countryCode: string | null;
/** @enum {string} */
profileVisibility: "hidden" | "logged_in_only" | "public";
/** @enum {string} */
jobSearchStatus: "actively_looking" | "open_to_offers" | "not_looking";
/** @enum {string} */
jobSearchStatusVisibleTo: "everyone" | "employers_only";
openToRelocate: boolean;
};
CandidateSkill: {
/** @enum {string} */
object: "candidate_skill";
name: string;
jobSkillId: string | null;
};
ClaimableCompany: {
id: string;
/** @enum {string} */
object: "claimable_company";
name: string;
slug: string;
website: string | null;
};
CompanyBillingPortalBody: {
returnPath?: string;
};
CompanyBillingPortalSession: {
/** @enum {string} */
object: "portal_session";
url: string;
};
CompanyCategorySalary: {
/** @enum {string} */
object: "company_category_salary";
categorySourceSlug: string;
categoryCanonicalSlug: string;
companyName: string;
companySlug: string;
companyLogoPath: string | null;
companyWebsite: string | null;
categoryName: string;
overallSalary: {
avgMin: number;
avgMax: number;
jobCount: number;
} | null;
bySeniority: {
seniority: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
boardAvgMin: number | null;
boardAvgMax: number | null;
boardMedianMin: number | null;
boardMedianMax: number | null;
boardP25Min: number | null;
boardP75Min: number | null;
boardP25Max: number | null;
boardP75Max: number | null;
diffPercent: number | null;
}[];
competitors: {
companySlug: string;
companyName: string;
logoPath: string | null;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
boardCategoryAvgMin: number | null;
boardCategoryAvgMax: number | null;
boardCategoryP25Min: number | null;
boardCategoryP75Max: number | null;
currency: string;
};
CompanyMarket: {
/** @enum {string} */
object: "company_market";
slug: string;
name: string;
/** @description Number of companies on the board in this market. */
companyCount: number;
};
CompanyMarketRef: {
/** @description Display name of the market. */
name: string;
/** @description Source slug for the market. Use it as the `:market` segment of the market-scoped company browse. */
slug: string;
};
CompanyMember: {
id: string;
/** @enum {string} */
object: "company_member";
boardUserId: string;
displayName: string | null;
email: string;
/** @enum {string} */
role: "admin" | "member";
approvedBy: string | null;
/** Format: date-time */
createdAt: string;
};
CompanyMemberInvite: {
id: string;
/** @enum {string} */
object: "company_member_invite";
email: string;
/** Format: date-time */
createdAt: string;
/** Format: date-time */
expiresAt: string;
};
CompanyMemberInviteAcceptance: {
/** @enum {string} */
object: "company_member_invite_acceptance";
companySlug: string;
};
CompanyMembership: {
id: string;
/** @enum {string} */
object: "company_membership";
/** @enum {string} */
status: "approved" | "pending_work_email" | "awaiting_admin" | "rejected";
role: string;
workEmail: string | null;
/** Format: date-time */
workEmailVerifiedAt: string | null;
company: {
id: string;
name: string;
slug: string | null;
website: string | null;
logoUrl: string | null;
};
};
CompanyPublic: {
/** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the company endpoints (e.g. `GET /v1/companies/{id}`). */
id: string;
/**
* @description String representing the object's type. Objects of the same type share the same value.
* @enum {string}
*/
object: "public_company";
/** @description Display name of the company. */
name: string;
/** @description URL-friendly slug for the company. */
slug: string;
/** @description Public company website URL, or `null` if not set. */
website: string | null;
/** @description URL of the company logo, or `null` if no logo is set. */
logoUrl: string | null;
/** @description Plain-text card teaser: the operator-authored company summary when set, otherwise a derived teaser from the long-form description (HTML stripped, first sentence / word-boundary cut). `null` when neither yields anything. Prefer this over `description` for list/card renders. */
summary: string | null;
/**
* @deprecated
* @description Long-form description of the company (HTML), or `null` if not set. **Deprecated on list/search/similar responses** — prefer `summary` for card teasers. Still the full prose for detail pages (`GET …/companies/{slug}`).
*/
description: string | null;
/** @description Total number of public-facing jobs at this company. Currently mirrors `publishedJobCount`. */
jobCount: number;
/** @description Number of currently-published, non-expired jobs at this company. */
publishedJobCount: number;
/** @description Number of jobs that contribute to this company's salary aggregates on the board (the salary sample size). `0` when there is no usable salary data — prefer this over fetching the full company-salary document just to decide whether to show a Salaries tab. Not the same as `publishedJobCount` (open roles without pay data stay at 0 here). */
salarySampleCount: number;
membership: components["schemas"]["PublicCompanyMembership"];
links: components["schemas"]["PublicCompanyLinks"];
};
CompanyPublicDetail: components["schemas"]["CompanyPublic"] & {
/** @description Markets (sectors) this company operates in, each with its source slug. Empty when the company has no markets. */
markets: components["schemas"]["CompanyMarketRef"][];
};
CompanySalary: {
/** @enum {string} */
object: "company_salary";
companyName: string;
companySlug: string;
companyLogoPath: string | null;
companyWebsite: string | null;
overallSalary: {
avgMin: number;
avgMax: number;
jobCount: number;
} | null;
bySeniority: {
seniority: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
boardAvgMin: number | null;
boardAvgMax: number | null;
boardMedianMin: number | null;
boardMedianMax: number | null;
boardP25Min: number | null;
boardP75Min: number | null;
boardP25Max: number | null;
boardP75Max: number | null;
diffPercent: number | null;
}[];
competitors: {
companySlug: string;
companyName: string;
logoPath: string | null;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
topLocations: {
locationName: string;
countryCode: string;
placeSlug: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
byCategory: {
categorySlug: string;
categoryName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
boardOverallAvgMin: number | null;
boardOverallAvgMax: number | null;
boardMedianMin: number | null;
boardMedianMax: number | null;
boardP25Min: number | null;
boardP75Min: number | null;
boardP25Max: number | null;
boardP75Max: number | null;
currency: string;
};
CompanySalarySummary: {
/** @enum {string} */
object: "company_salary_summary";
companyName: string;
companySlug: string;
overallSalary: {
avgMin: number;
avgMax: number;
jobCount: number;
} | null;
/** @description Top job categories at the company by sample size (capped; full list is on CompanySalary.byCategory). Category names/slugs are board-language localized. */
topCategories: {
categorySlug: string;
categoryName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
/** @description Jobs contributing to this company's salary aggregates (same meaning as CompanyPublic.salarySampleCount / overallSalary.jobCount). */
sampleCount: number;
currency: string;
};
CompanySuggestion: {
/** @enum {string} */
object: "suggestion";
/**
* @description discriminator enum property added by openapi-typescript
* @enum {string}
*/
type: "company";
/** @description Stable company identity. */
id: string;
/** @description Public company URL slug. */
slug: string;
/** @description Company display name. */
name: string;
/** @description Company logo URL, or `null` when none is set. */
logoUrl: string | null;
/** @description Live published-job count for this company on the board. */
jobCount: number;
};
ConfirmEmailChangeBody: {
token: string;
};
ConfirmWorkEmailBody: {
token: string;
};
Conversation: {
id: string;
/** @enum {string} */
object: "conversation";
/** Format: date-time */
lastMessageAt: string;
lastMessageSnippet: string;
lastMessageAuthorBoardUserId: string;
/** Format: date-time */
archivedAt: string | null;
hasUnread: boolean;
counterparty: components["schemas"]["ConversationCounterparty"];
};
ConversationArchive: {
/** @enum {string} */
object: "conversation_archive";
/** Format: date-time */
archivedAt: string | null;
};
ConversationCounterparty: {
boardUserId: string;
displayName: string;
avatarUrl: string | null;
companyName: string | null;
handle: string | null;
companySlug: string | null;
};
ConversationDetail: components["schemas"]["Conversation"] & {
/** @enum {string} */
viewerRole: "employer" | "candidate";
viewerLastReadMessageId: string | null;
};
ConversationRef: {
/** @enum {string} */
object: "conversation_ref";
conversationId: string | null;
};
ConvertSourcedCandidateBody: {
stage: string;
};
CreateApplyApprovalBody: {
sessionKey: string;
};
CreateApplyIntentBody: {
sessionKey: string;
};
CreateCompanyBody: {
/** @description Public company website URL. Normalized to a canonical apex domain when stored. */
website?: string;
/** @description One-line summary of the company. Up to 280 characters. */
summary?: string;
/** @description Long-form description of the company. Up to 25,000 characters. */
description?: string;
/** @description X (Twitter) profile URL or handle. Stored as the canonical handle. */
xUrl?: string;
/** @description LinkedIn company page URL. */
linkedinUrl?: string;
/** @description Facebook company page URL. */
facebookUrl?: string;
/** @description Canonical market slugs assigned to the company. Pass an empty array to clear all markets. */
markets?: string[];
/** @description The company's display name. */
name: string;
/** @description URL-friendly slug for the company. Auto-generated from `name` when omitted. */
slug?: string;
};
CreateCompanyMemberInviteBody: {
/** Format: email */
email: string;
};
CreateEducationBody: {
institutionName: string;
institutionUrl?: string;
degree?: string;
fieldOfStudy?: string;
grade?: string;
activitiesAndSocieties?: string;
startDate?: string;
endDate?: string;
description?: string;
sortOrder?: number;
};
CreateExperienceBody: {
title: string;
companyName: string;
startDate: string;
companyUrl?: string;
location?: string;
employmentType?: string;
locationType?: string;
foundVia?: string;
endDate?: string;
description?: string;
sortOrder?: number;
};
CreateJobPostingBody: {
submission: {
companyName: string;
companyWebsite?: string;
contactName: string;
contactEmail: string;
title: string;
description: string;
employmentType: string;
remoteOption: string;
officeLocations: {
/** @enum {string} */
provider?: "mapbox";
providerPlaceId?: string;
displayName: string;
countryCode?: string;
region?: string;
locality?: string;
city?: string;
latitude?: number;
longitude?: number;
boundingBox?: number[];
raw?: {
suggestion?: {
[key: string]: unknown;
};
retrieve?: {
[key: string]: unknown;
};
};
}[];
inOfficePeriod?: string;
inOfficeFrequency?: number;
seniority?: string;
applicationUrl: string;
salaryRangeEnabled: boolean;
salaryMin?: number;
salaryMax?: number;
salaryTimeframe?: string;
salaryCurrency?: string;
selectedPlan?: string;
isFeatured?: boolean;
remoteWorkingPermits?: {
type: string;
value: string;
label: string;
}[];
remoteTimezones?: {
type: string;
value: string;
label: string;
plusMinus: number;
offset?: number;
}[];
/** @enum {string} */
remoteSponsorship?: "yes" | "no" | "unknown";
customFieldValues?: {
[key: string]: string | string[] | boolean | number;
};
};
remoteAllowedTzOffsets?: number[];
remoteWorkPermitCountryCodes?: string[];
logoUrl?: string;
selectedBilling?: {
type: string;
id?: string;
planId: string;
};
invoiceBilling?: {
billingName?: string;
address: {
line1?: string;
city?: string;
postalCode?: string;
country?: string;
};
taxId?: string;
buyerAnswers?: {
contactName?: string;
custom: {
[key: string]: string;
};
};
/**
* @deprecated
* @description Deprecated — use buyerAnswers.
*/
detailFields?: {
name: string;
value: string;
}[];
};
colorMode?: string;
};
CreatePipelineStageBody: {
/** @description The job whose pipeline gains the stage. */
jobId: string;
/** @description The stage label. */
label: string;
};
CreateTalentListBody: {
name: string;
filters?: components["schemas"]["TalentListFilters"];
job?: string;
};
CustomFieldDefinition: {
/** @description Immutable per-board slug used as the key in a job’s `customFieldValues`. */
key: string;
/** @description Authoring-default label; the localized public string lives in the board template. */
label: string;
/**
* @description Field type, which dictates the value: `short_text`/`long_text` → string; `single_select` → one option key; `multi_select` → array of option keys; `boolean` → boolean; `number` → number.
* @enum {string}
*/
type: "short_text" | "long_text" | "single_select" | "multi_select" | "boolean" | "number";
/** @description Present only for `single_select`/`multi_select`. A stored value is one (or, for multi, several) of these option `key`s — never a label. */
options?: components["schemas"]["CustomFieldOption"][];
/** @description When true, the value cannot be cleared or left empty on a write (rejected with `custom_field_required`). */
required: boolean;
/** @description Inclusive minimum for `number` fields, when set. */
min?: number;
/** @description Inclusive maximum for `number` fields, when set. */
max?: number;
};
CustomFieldOption: {
/** @description Stable option key — the value stored on a job, not the label. */
key: string;
/** @description Display label (authoring default; localized per board in the template). */
label: string;
};
EditMessageBody: {
body: string;
};
EmployerApplicant: {
id: string;
/** @enum {string} */
object: "employer_applicant";
jobId: string;
candidateBoardUserId: string | null;
candidateProfileId: string | null;
candidateProfileHandle: string | null;
candidateName: string | null;
candidateEmail: string | null;
candidateHeadline: string | null;
candidateLocation: string | null;
coverNote: string | null;
resumeFilename: string | null;
/** @description A short-lived signed URL to the uploaded resume, or `null`. */
resumeUrl: string | null;
stage: string;
/** @description How the application arrived (e.g. `native_apply`). */
source: string;
/** Format: date-time */
appliedAt: string;
timeline: components["schemas"]["EmployerApplicantTimelineEntry"][];
};
EmployerApplicantTimelineEntry: {
id: string;
/** @description The activity kind (e.g. `stage_changed`, `note_created`, `application_created`). */
type: string;
actorBoardUserId: string | null;
actorName: string | null;
noteId: string | null;
/** @description The note text for a `note_created` entry, else `null`. */
noteBody: string | null;
fromStage: string | null;
toStage: string | null;
/** Format: date-time */
createdAt: string;
};
EmployerBillingOption: {
id: string;
/** @enum {string} */
object: "employer_billing_option";
/** @enum {string} */
type: "subscription" | "order" | "plan_assignment";
/** @enum {string} */
kind?: "member_post";
planId: string;
planName: string;
/** @enum {string} */
planKind: "subscription" | "one_time" | "bundle";
jobsRemaining: number;
jobsTotal: number;
featuredRemaining: number;
featuredTotal: number;
/** @description True when this option grants unlimited job posts; jobsRemaining/jobsTotal are then not meaningful. */
jobsUnlimited?: boolean;
/** @description True when this option grants unlimited featured posts. */
featuredUnlimited?: boolean;
/**
* Format: date-time
* @description When a subscription renews, or `null` for one-time orders.
*/
renewsAt: string | null;
};
EmployerCheckout: {
/** @enum {string} */
object: "employer_checkout";
/** @enum {string} */
status: "checkout" | "published" | "invoice_sent";
/** @description The Stripe Checkout / hosted-invoice URL, or `null`. */
checkoutUrl: string | null;
jobId: string;
jobSlug: string | null;
};
EmployerCheckoutBody: {
billing: {
/** @enum {string} */
type: "new";
planId: string;
} | {
/** @enum {string} */
type: "order";
planId: string;
id: string;
} | {
/** @enum {string} */
type: "subscription";
planId: string;
id: string;
} | {
/** @enum {string} */
type: "plan_assignment";
planId?: string;
id?: string;
};
invoiceBilling?: {
billingName?: string;
/** Format: email */
email?: string;
address?: {
line1?: string;
city?: string;
postalCode?: string;
country?: string;
};
taxId?: string;
buyerAnswers?: {
contactName?: string;
custom: {
[key: string]: string;
};
};
/**
* @deprecated
* @description Deprecated — use buyerAnswers.
*/
detailFields?: {
name: string;
value: string;
}[];
};
isFeatured?: boolean;
/**
* Format: uri
* @description Where Stripe returns the buyer on success. Defaults to the board's canonical employer pages.
*/
successUrl?: string;
/**
* Format: uri
* @description Where Stripe returns the buyer on cancel.
*/
cancelUrl?: string;
};
EmployerCompany: {
id: string;
/** @enum {string} */
object: "employer_company";
name: string;
slug: string;
website: string | null;
description: string | null;
summary: string | null;
xUrl: string | null;
linkedinUrl: string | null;
facebookUrl: string | null;
logoUrl: string | null;
/** @description Whether company admins may delete this company. Mirrors the board Features toggle `employerCompanyDeletionEnabled`. Absent board config defaults to `true`. When `false`, DELETE returns 403 `company_deletion_disabled` and clients should hide the danger zone. */
deletionEnabled: boolean;
};
EmployerCreateJobBody: {
/** @description Long-form description of the role. Up to 25,000 characters. */
description: string;
/** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
slug?: string;
/**
* @description Employment type of the role.
* @enum {string}
*/
employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
/**
* @description Whether the role is on-site, hybrid, or fully remote. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{"type":"worldwide","value":"worldwide"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`.
* @enum {string}
*/
remoteOption?: "on_site" | "hybrid" | "remote";
/** @description Where remote candidates must hold work authorization. Each entry is the smallest relevant scope: `worldwide`, a `world_region` (EMEA / LATAM / NA / APAC), a `continent`, a `region`, a `subregion`, a `custom` group (e.g. `EU`), a `country` (ISO 3166-1 alpha-2), or a `subdivision` (ISO 3166-2). Subdivisions auto-imply their parent country in the derived `remoteWorkPermitCountryCodes` output. Worldwide is mutually exclusive with all other entries. The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-permits`. Pass `[]` to clear an existing constraint. */
remotePermits?: {
/** @enum {string} */
type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
value: string;
}[];
/** @description Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name with optional `plusMinus` ±N hours expansion) and `all` (every timezone: equivalent of `worldwide` for permits). The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-timezones`. **When omitted on POST**, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). **PATCH never auto-re-derives**: once set, only an explicit replacement updates the stored value, even when `remotePermits` changes. Pass `[]` to clear an existing constraint. */
remoteTimezones?: {
/** @enum {string} */
type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
value: string;
plusMinus?: number;
}[];
/**
* @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
* @enum {string}
*/
remoteSponsorship?: "yes" | "no" | "unknown";
/**
* @description Seniority level of the role.
* @enum {string}
*/
seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
/** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (normalized to `mailto:` form). Omit to collect applications on the board (built-in applications). */
applicationUrl?: string;
/** @description Minimum salary, in `salaryCurrency` units. */
salaryMin?: number;
/** @description Maximum salary, in `salaryCurrency` units. */
salaryMax?: number;
/** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
salaryCurrency?: string;
/**
* @description Period the `salaryMin` and `salaryMax` figures are quoted against.
* @enum {string}
*/
salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
/** @description Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account. */
skills?: string[];
/** @description Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account. */
categories?: string[];
/** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
/** @description Minimum required experience, expressed in months. */
experienceMonths?: number;
/** @description If `true`, equivalent experience may substitute for the listed education requirements. */
experienceInPlaceOfEducation?: boolean;
/**
* @description Period denominator for `inOfficeFrequency`.
* @enum {string}
*/
inOfficePeriod?: "per_week" | "per_month" | "per_year";
/** @description How often the candidate must be in-office over `inOfficePeriod`. */
inOfficeFrequency?: number;
/** @description Physical office locations associated with the job. Prefer `{query: "City, Country"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
/** @description The job title. */
title: string;
};
EmployerJob: components["schemas"]["EmployerJobSummary"] & {
/** @description Long-form description of the role, or `null` if not specified. */
description: string | null;
/** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
applicationUrl: string | null;
/** @description Hierarchical permit selection authored by the employer. The three `remoteWorkPermit*` and `remoteWorldwide` fields are read-only derived projections. */
remotePermits: {
type: string;
value: string;
}[];
/** @description Read-only: derived from `remotePermits`. */
remoteWorldwide: boolean | null;
/** @description Hierarchical timezone selection. The flat `remoteAllowedTzOffsets` below is the read-only derived projection. */
remoteTimezones: {
type: string;
value: string;
plusMinus?: number;
}[];
/** @description Read-only: derived from `remoteTimezones`. UTC hour offsets. */
remoteAllowedTzOffsets: number[];
/** @description Read-only: derived from `remotePermits`. ISO 3166-1 alpha-2. */
remoteWorkPermitCountryCodes: string[];
/** @description Read-only: derived from `remotePermits`. ISO 3166-2. */
remoteWorkPermitSubdivisionCodes: string[];
/**
* @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
* @enum {string}
*/
remoteSponsorship: "yes" | "no" | "unknown";
/** @description Required education credentials. */
educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
/** @description Minimum required experience in months, or `null`. */
experienceMonths: number | null;
/** @description If `true`, equivalent experience may substitute for education. `null` if not specified. */
experienceInPlaceOfEducation: boolean | null;
/**
* @description Period denominator for `inOfficeFrequency`, or `null`.
* @enum {string|null}
*/
inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
/** @description How often the candidate must be in-office, or `null`. */
inOfficeFrequency: number | null;
company: components["schemas"]["JobCompany"];
/** @description Physical office locations associated with the job. */
officeLocations: components["schemas"]["JobOfficeLocation"][];
};
/** @description Public-only links. The operator dashboard URL is intentionally omitted on employer responses. */
EmployerJobLinks: {
/**
* Format: uri
* @description Canonical public URL for this job, or `null` when the job has no slug or no associated company slug (so a stable URL cannot be assembled). A draft carries a URL but only resolves once published.
*/
public: string | null;
};
EmployerJobStat: {
/** @enum {string} */
object: "employer_job_stat";
/** @description The job ID these stats belong to. */
jobId: string;
/** @description Job-detail page-views over the all-time window. */
views: number;
/** @description Apply-click events over the all-time window. */
applyClicks: number;
/** @description Native ATS application count, or `null` for an external-apply job (no native pipeline). */
applications: number | null;
};
EmployerJobStatsPoint: {
/** @enum {string} */
object: "employer_job_stats_point";
/** @description The UTC day this bucket covers (`YYYY-MM-DD`). */
date: string;
/** @description Job-detail page-views on this day. */
views: number;
/** @description Apply-click events on this day. */
applyClicks: number;
};
EmployerJobSummary: {
/** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
id: string;
/**
* @description String representing the object's type. Objects of the same type share the same value.
* @enum {string}
*/
object: "employer_job";
/** @description The job title. */
title: string;
/** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
slug: string | null;
/**
* @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
* @enum {string}
*/
status: "draft" | "published" | "expired" | "archived";
/** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
companyId: string | null;
/**
* @description Employment type of the role, or `null` if not specified.
* @enum {string|null}
*/
employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
/**
* @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
* @enum {string|null}
*/
remoteOption: "on_site" | "hybrid" | "remote" | null;
/**
* @description Seniority level of the role, or `null` if not specified.
* @enum {string|null}
*/
seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
/** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
salaryMin: number | null;
/** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
salaryMax: number | null;
/** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
salaryCurrency: string | null;
/**
* @description Period the salary range is quoted against, or `null` if no salary is specified.
* @enum {string|null}
*/
salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
/** @description Whether the job appears in featured slots on the public board. */
isFeatured: boolean;
/** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
publishedAt: string | null;
/** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
expiresAt: string | null;
/** @description Time at which the job was created. ISO 8601 datetime. */
createdAt: string;
/** @description Time at which the job was last updated. ISO 8601 datetime. */
updatedAt: string;
links: components["schemas"]["EmployerJobLinks"];
};
EmployerPipeline: {
/** @enum {string} */
object: "employer_pipeline";
job: {
id: string;
title: string;
status: string;
/** Format: date-time */
expiresAt: string | null;
};
stages: components["schemas"]["EmployerPipelineStage"][];
applicants: components["schemas"]["EmployerApplicant"][];
};
EmployerPipelineStage: {
id: string;
/** @enum {string} */
object: "employer_pipeline_stage";
jobId: string;
label: string;
/**
* @description The stable system meaning, or `null` for a custom employer stage.
* @enum {string|null}
*/
systemStage: "shortlisted" | "contacted" | "replied" | "review" | "offer" | "hired" | "rejected" | null;
isProtected: boolean;
hidden: boolean;
position: number;
};
EmployerPostingCapabilities: {
canPost: boolean;
/** @enum {string} */
reason?: "membership_required";
discountPercent: number;
freePostsRemaining: number;
/** @description True when an active membership grants unlimited posts. */
freePostsUnlimited?: boolean;
memberPlanName?: string;
};
EmployerProfileStats: {
/** @enum {string} */
object: "employer_profile_stats";
/** @description Company profile-page views over the all-time window (tabs and bots excluded). */
profileViews: number;
};
EmployerProfileViewsPoint: {
/** @enum {string} */
object: "employer_profile_views_point";
/** @description The UTC day this bucket covers (`YYYY-MM-DD`). */
date: string;
/** @description Company profile-page views on this day. */
views: number;
};
EmployerUpdateJobBody: {
/** @description Long-form description of the role. Up to 25,000 characters. */
description?: string;
/** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
slug?: string;
/**
* @description Employment type of the role.
* @enum {string}
*/
employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
/**
* @description Whether the role is on-site, hybrid, or fully remote. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{"type":"worldwide","value":"worldwide"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`.
* @enum {string}
*/
remoteOption?: "on_site" | "hybrid" | "remote";
/** @description Where remote candidates must hold work authorization. Each entry is the smallest relevant scope: `worldwide`, a `world_region` (EMEA / LATAM / NA / APAC), a `continent`, a `region`, a `subregion`, a `custom` group (e.g. `EU`), a `country` (ISO 3166-1 alpha-2), or a `subdivision` (ISO 3166-2). Subdivisions auto-imply their parent country in the derived `remoteWorkPermitCountryCodes` output. Worldwide is mutually exclusive with all other entries. The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-permits`. Pass `[]` to clear an existing constraint. */
remotePermits?: {
/** @enum {string} */
type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
value: string;
}[];
/** @description Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name with optional `plusMinus` ±N hours expansion) and `all` (every timezone: equivalent of `worldwide` for permits). The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-timezones`. **When omitted on POST**, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). **PATCH never auto-re-derives**: once set, only an explicit replacement updates the stored value, even when `remotePermits` changes. Pass `[]` to clear an existing constraint. */
remoteTimezones?: {
/** @enum {string} */
type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
value: string;
plusMinus?: number;
}[];
/**
* @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
* @enum {string}
*/
remoteSponsorship?: "yes" | "no" | "unknown";
/**
* @description Seniority level of the role.
* @enum {string}
*/
seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
/** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (normalized to `mailto:` form). Pass `null` to clear the stored value and switch the job to on-board (built-in) applications. Omitted means unchanged. */
applicationUrl?: string | null;
/** @description Minimum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. */
salaryMin?: number | null;
/** @description Maximum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. */
salaryMax?: number | null;
/** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. Pass `null` to clear the stored value; omitted means unchanged. */
salaryCurrency?: string | null;
/**
* @description Period the `salaryMin` and `salaryMax` figures are quoted against. Pass `null` to clear the stored value; omitted means unchanged.
* @enum {string|null}
*/
salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
/** @description Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account. */
skills?: string[];
/** @description Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account. */
categories?: string[];
/** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
/** @description Minimum required experience, expressed in months. */
experienceMonths?: number;
/** @description If `true`, equivalent experience may substitute for the listed education requirements. */
experienceInPlaceOfEducation?: boolean;
/**
* @description Period denominator for `inOfficeFrequency`.
* @enum {string}
*/
inOfficePeriod?: "per_week" | "per_month" | "per_year";
/** @description How often the candidate must be in-office over `inOfficePeriod`. */
inOfficeFrequency?: number;
/** @description Physical office locations associated with the job. Prefer `{query: "City, Country"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
/** @description The job title. */
title?: string;
};
/** @description The error envelope returned by every non-2xx response. */
Error: {
error: {
/** @description Machine-readable error code, such as `validation_bad_request` or `jobs_not_found`. */
code: string;
/** @description Human-readable explanation. */
message: string;
/** @description Unique id for this request. Include it when contacting support. */
requestId: string;
/** @description Structured context for some errors, such as per-field validation issues. */
details?: unknown;
};
};
HandleAvailability: {
/** @enum {string} */
object: "handle_availability";
handle: string;
available: boolean;
};
/** @description Embedded company resource for the job, or `null` if no company is attached. */
JobCompany: {
/** @description Unique identifier for the company. */
id: string;
/** @description Display name of the company, or `null` if not yet set. */
name: string | null;
/** @description URL slug of the company, or `null` if not yet set. */
slug: string | null;
/** @description URL of the company logo, or `null` if no logo is set. */
logoUrl: string | null;
/** @description Company website URL, or `null` if no website is set. */
website: string | null;
} | null;
JobOfficeLocation: {
/** @description ISO 3166-1 alpha-2 country code, or `null` if the location was not resolved. */
countryCode: string | null;
/** @description Full country name, or `null` if the location was not resolved. */
country: string | null;
/** @description Neighborhood or sub-locality, or `null` if not resolved. */
locality: string | null;
/** @description City, or `null` if not resolved. */
city: string | null;
/** @description Region, state, or province name, or `null` if not resolved. */
region: string | null;
/** @description Region or state code (e.g. `CA` for California), or `null` if not resolved. */
regionCode: string | null;
/** @description Postal or ZIP code, or `null` if not resolved. */
postalCode: string | null;
/** @description Pre-formatted display name for the location, or `null` if not resolved. */
displayName: string | null;
};
JobOfficeLocationInput: {
/** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Utrecht, Netherlands"`, `"Mountain View, California, USA"`). Resolved server-side; rejected when no high-confidence match is found. */
query: string;
} | {
/** @description Neighborhood or sub-locality. */
locality?: string;
/** @description City. */
city: string;
/** @description Region, state, or province. */
region?: string;
/** @description ISO 3166-1 alpha-2 country code OR recognized country name/alias. Aliases are normalized to canonical alpha-2 server-side (e.g. `US`, `USA`, `United States` → `US`; `UK`, `GB`, `United Kingdom` → `GB`). */
country: string;
};
JobPostingBillingOptions: {
/** @enum {string} */
object: "job_posting_billing_options";
options: {
id: string;
type: string;
planId: string;
planName: string;
planKind: string;
capacities: {
key: string;
total: number;
used: number;
remaining: number;
}[];
jobsRemaining: number;
jobsTotal: number;
featuredRemaining: number;
featuredTotal: number;
renewsAt: string | null;
}[];
};
JobPostingBillingOptionsBody: {
verificationToken: string;
};
JobPostingBillingVerification: {
/** @enum {string} */
object: "job_posting_billing_verification";
success: boolean;
};
JobPostingLogo: {
/** @enum {string} */
object: "job_posting_logo";
publicUrl: string;
};
JobPostingPlan: {
/** @enum {string} */
object: "job_posting_plan";
id: string;
name: string;
description: string | null;
kind: string;
/** @enum {string|null} */
billingInterval: "month" | "year" | null;
/** @enum {string|null} */
purpose: "job_posting" | "talent_access" | null;
isRecommended: boolean;
displayOrder: number | null;
invoiceOnly: boolean;
/** @enum {string|null} */
publishTiming: "on_issue" | "on_payment" | null;
netTermsDays: number | null;
prices: {
currency: string;
amountCents: number;
isActive: boolean;
}[];
features: {
key: string | null;
value: string | null;
}[];
};
JobPostingResult: {
/** @enum {string} */
object: "job_posting_result";
/** @enum {string} */
status: "checkout";
checkoutUrl: string;
jobId: string;
} | {
/** @enum {string} */
object: "job_posting_result";
/** @enum {string} */
status: "published";
jobId: string;
jobSlug: string;
} | {
/** @enum {string} */
object: "job_posting_result";
/** @enum {string} */
status: "pending_approval";
jobId: string;
} | {
/** @enum {string} */
object: "job_posting_result";
/** @enum {string} */
status: "invoice_sent";
jobId: string;
};
JobPostingSendVerificationBody: {
/** Format: email */
email: string;
};
LocationSalaryDetail: {
/** @enum {string} */
object: "location_salary_detail";
/** @description Immutable English source place slug: the salary-stats key. */
sourceSlug: string;
/** @description Board-language canonical URL slug: the starter 308 target. */
canonicalSlug: string;
placeName: string;
placeId: string;
adminLevel: string;
countryCode: string;
overallSalary: {
avgMin: number;
avgMax: number;
medianMin: number;
medianMax: number;
p25Min: number;
p75Max: number;
jobCount: number;
} | null;
childLocations: {
placeName: string;
placeSlug: string;
countryCode: string;
avgSalaryMin: number;
avgSalaryMax: number;
medianSalaryMin: number;
medianSalaryMax: number;
p25SalaryMin: number;
p75SalaryMax: number;
jobCount: number;
currency: string;
}[];
childLocationsByRegion: {
regionName: string;
regionSlug: string;
cities: {
placeName: string;
placeSlug: string;
countryCode: string;
avgSalaryMin: number;
avgSalaryMax: number;
medianSalaryMin: number;
medianSalaryMax: number;
p25SalaryMin: number;
p75SalaryMax: number;
jobCount: number;
currency: string;
}[];
}[];
topCategories: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
categorySlug: string;
categoryName: string;
}[];
topSkills: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
skillSlug: string;
skillName: string;
}[];
siblingLocations: {
placeName: string;
placeSlug: string;
countryCode: string;
avgSalaryMin: number;
avgSalaryMax: number;
medianSalaryMin: number;
medianSalaryMax: number;
p25SalaryMin: number;
p75SalaryMax: number;
jobCount: number;
currency: string;
}[];
boardOverallAvgMin: number | null;
boardOverallAvgMax: number | null;
currency: string;
};
LocationSkillsIndex: {
/** @enum {string} */
object: "location_skills_index";
sourceSlug: string;
canonicalSlug: string;
placeName: string;
skills: {
slug: string;
name: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
};
LocationTitlesIndex: {
/** @enum {string} */
object: "location_titles_index";
sourceSlug: string;
canonicalSlug: string;
placeName: string;
titles: {
slug: string;
name: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
};
MarketSuggestion: {
/** @enum {string} */
object: "suggestion";
/**
* @description discriminator enum property added by openapi-typescript
* @enum {string}
*/
type: "market";
/** @description Stable market identity (source slug; markets are slug-keyed). */
id: string;
/** @description Public market URL slug. */
slug: string;
/** @description Market display name. */
name: string;
/** @description Number of companies on the board in this market. */
companyCount: number;
};
MarketingConsent: {
id: string;
/** @enum {string} */
object: "marketing_consent";
/** @enum {string} */
status: "granted" | "withdrawn";
source: string;
/** @enum {string|null} */
reason: "person_request" | "operator_request" | "account_deleted" | null;
/** Format: date-time */
grantedAt: string | null;
/** Format: date-time */
withdrawnAt: string | null;
revision: number;
} | null;
MembershipCheckoutBody: {
/** @description A public, priced `membership` or `employer_service` plan on this board (`GET /boards/{identifier}/plans`). */
planId: string;
returnPath: string;
/** @enum {string} */
colorMode: "light" | "dark";
};
Message: {
id: string;
/** @enum {string} */
object: "message";
conversationId: string;
authorBoardUserId: string;
recipientBoardUserId: string;
body: string;
author: components["schemas"]["MessageAuthor"];
/** Format: date-time */
sentAt: string;
/** Format: date-time */
editedAt: string | null;
/** Format: date-time */
deletedAt: string | null;
/** Format: date-time */
readAt: string | null;
};
MessageAuthor: {
displayName: string;
avatarUrl: string | null;
companyName: string | null;
};
ModerationReport: {
/** @enum {string} */
object: "moderation_report";
id: string;
blocked: boolean;
};
MoveApplicantStageBody: {
/** @description The target stage id. */
stageId: string;
};
NotificationPreference: {
/** @enum {string} */
object: "notification_preference";
/** @enum {string} */
channel: "messageEmails" | "applicationEmails" | "recommendedJobEmails";
subscribed: boolean;
waitlisted: boolean;
updatedAt: number | null;
};
PaywallOffer: {
/** @enum {string} */
object: "paywall_offer";
/** @description The tier key posted to checkout (e.g. `monthly`, `lifetime`). */
offerKey: string;
label: string;
billingLabel: string;
amountCents: number;
currency: string;
/**
* @description `recurring` tiers get a manage-subscription portal; `lifetime` do not.
* @enum {string}
*/
offerType: "recurring" | "lifetime";
intervalUnit: string | null;
intervalCount: number | null;
isDefault: boolean;
};
Plan: {
/** @enum {string} */
object: "plan";
id: string;
/** @description The operator's authoring-default plan name, in the board's language. Board templates that localize chrome should treat this as the fallback and word plan names from `featureSummary` structure or their own catalogs. */
name: string;
/** @description Authoring default: the operator's prose description in the board's language. The localized public string lives in the board template — compose it from `featureSummary`, `billingInterval`, and `talent` rather than displaying this verbatim on localized surfaces. */
description: string | null;
/** @enum {string} */
purpose: "job_posting" | "talent_access" | "membership" | "job_seeker" | "employer_service" | "job_seeker_service";
/** @enum {string} */
kind: "free" | "subscription" | "one_time" | "bundle";
/** @enum {string|null} */
billingInterval: "day" | "week" | "month" | "year" | null;
/** @description Stripe recurring.interval_count. Null means 1. Quarterly is month × 3. */
billingIntervalCount: number | null;
isRecommended: boolean;
displayOrder: number;
/**
* @description How the plan is sold. `priced` is bought with `price.stripePriceId`; `contact` is quote-only and must render the CTA below instead of a price. Read this, never `price` — a contact plan can still carry a zeroed price row. Plans created before this field existed report `priced`.
* @enum {string}
*/
pricingMode: "priced" | "contact";
/** @description Operator-authored display price for a contact plan, e.g. "From $2,000" or "15% of first-year salary". Null when unset. */
priceText: string | null;
/** @description Operator-authored CTA label for a contact plan. Null when unset; supply your own wording. */
ctaText: string | null;
/** @description The CTA target: an https, mailto:, or tel: URL. Null when unset, in which case render no CTA rather than a dead control. */
ctaDestination: string | null;
invoiceOnly: boolean;
/** @enum {string|null} */
publishTiming: "on_issue" | "on_payment" | null;
netTermsDays: number | null;
price: {
currency: string;
amountCents: number;
/** @description The public Stripe Price id used to start checkout. */
stripePriceId: string | null;
} | null;
/**
* @deprecated
* @description Job-posting feature summary. **Deprecated** — superseded by `features`, which carries the same benefits keyed by canonical feature key. Still serialized for compatibility.
*/
featureSummary: {
durationDays: number;
maxActiveJobs: number;
featuredSlots: number;
/** @enum {string} */
featureSelectionMode: "auto" | "manual";
};
/**
* @deprecated
* @description Talent-access allowances (per billing period). Present only when `purpose` is `talent_access`. `"unlimited"` is a sentinel value. **Deprecated** — superseded by `features`, which carries the same allowances keyed by canonical feature key. Still serialized for compatibility.
*/
talent?: {
unlocksPerPeriod: string;
messagesPerPeriod: string;
};
/** @description Self-describing map of every benefit the plan carries, keyed by the canonical feature key. Each entry includes the value and enough of the feature definition (name, dataType, and optional displayOrder) to render without a second call. Values are strings; the literal "unlimited" is a sentinel and must be kept as a string. New features, including operator-defined custom attributes, appear here with no schema change. The API returns no display copy. */
features: {
[key: string]: {
value: string;
name: string;
dataType: string;
displayOrder?: number;
};
};
};
PostSuggestion: {
/** @enum {string} */
object: "suggestion";
/**
* @description discriminator enum property added by openapi-typescript
* @enum {string}
*/
type: "post";
/** @description Stable published blog post identity. */
id: string;
/** @description Public blog post URL slug. */
slug: string;
/** @description Post title. */
title: string;
};
PublicBlogAdjacentPosts: {
/** @enum {string} */
object: "blog_adjacent_posts";
previous: components["schemas"]["PublicBlogPostSummary"] | null;
next: components["schemas"]["PublicBlogPostSummary"] | null;
};
PublicBlogAuthor: components["schemas"]["PublicBlogAuthorEmbed"] & {
/** @enum {string} */
object: "public_blog_author";
};
PublicBlogAuthorEmbed: {
id: string;
name: string;
slug: string;
bio: string | null;
location: string | null;
avatarUrl: string | null;
websiteUrl: string | null;
facebookUrl: string | null;
twitterUrl: string | null;
linkedinUrl: string | null;
githubUrl: string | null;
};
PublicBlogPost: components["schemas"]["PublicBlogPostSummary"] & {
html: string | null;
ogImageUrl: string | null;
featureImageCaption: string | null;
seoTitle: string | null;
seoDescription: string | null;
redirected: boolean;
newSlug: string | null;
};
PublicBlogPostSummary: {
id: string;
/** @enum {string} */
object: "public_blog_post";
title: string;
slug: string;
featured: boolean;
coverUrl: string | null;
featureImageAlt: string | null;
customExcerpt: string | null;
readingTimeMin: number | null;
publishedAt: string | null;
canonicalUrl: string | null;
createdAt: string;
authors: components["schemas"]["PublicBlogAuthorEmbed"][];
tags: components["schemas"]["PublicBlogTagEmbed"][];
};
PublicBlogSearchBody: {
/** @description Free-text search query. Up to 200 characters. */
query: string;
/** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
cursor?: string | null;
/** @description A limit on the number of objects to be returned. Limit can range between 1 and 50. */
limit?: number;
/**
* @description The number of posts to skip — the search page offset. Takes precedence over `cursor`; pair with the response `count` to page in parallel. `offset + limit` may not exceed 10,000.
* @example 0
*/
offset?: number;
};
PublicBlogTag: components["schemas"]["PublicBlogTagEmbed"] & {
/** @enum {string} */
object: "public_blog_tag";
};
PublicBlogTagEmbed: {
id: string;
name: string;
slug: string;
description: string | null;
};
PublicBoardContext: {
/** @enum {string} */
object: "public_board";
/** @description Immutable board identifier (`boards_…`). */
id: string;
/** @description Mutable canonical board slug. */
slug: string;
name: string;
/** @description Board language (ISO code); defaults to "en". */
language: string;
/** @description Absolute URL for the board logo, or null when unset. Operators set this under Settings → General (upload or logo generator); the website builder can manage it too. */
logoUrl: string | null;
/** @description Absolute URLs for the favicon / app-icon pack derived from the board logo (null when a variant is unset). Brand identity next to `logoUrl` — build `` tags and the web-manifest icon list from these. Not SEO infra (`board.seo()`). */
icons: {
ico: string | null;
svg: string | null;
appleTouch: string | null;
icon192: string | null;
icon512: string | null;
iconMaskable512: string | null;
};
/** @description Active custom-domain hostname, or null. */
primaryDomain: string | null;
/** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
showCavunoBranding: boolean;
features: {
jobAlerts: boolean;
/** @description Whether personalized candidate job recommendations are available on this board. Absent board config defaults to `true`. */
jobRecommendationsEnabled: boolean;
/** @description Whether the board-level Recommended talent toggle is enabled. The endpoint additionally requires the Candidate area and a non-off talent directory. Absent board config defaults to `false`. */
recommendedTalentEnabled: boolean;
candidates: boolean;
employers: boolean;
blog: boolean;
/**
* @description Talent directory access mode. Link /talent whenever this is not `'off'`. An employers-only directory renders a sign-in upsell for anonymous visitors, matching the hosted chrome. Replaces the former top-level `talentDirectoryVisibility` and the boolean `features.talentDirectory`.
* @enum {string}
*/
talentDirectory: "off" | "public" | "employers_only";
registrationWall: boolean;
passwordProtected: boolean;
publicJobSubmission: boolean;
candidatePaywall: boolean;
impressum: boolean;
/** @description Whether the board accepts native (on-board ATS) applications. `false` means external-applications-only: the server rejects native submissions to `POST /jobs/:jobSlug/apply` with `applications_native_disabled` (422). Clients should hide native apply UI and treat a job with no external `applicationUrl` as not-applyable. */
nativeApplications: boolean;
/** @description Whether applicant↔employer messaging is enabled on the board. `false` means the `me/conversations` route family rejects with `messaging_disabled` (403). Hide inbox/dock/Message CTAs. */
messaging: boolean;
};
/**
* @description How the operator charges employers for the candidate directory. `paid_messaging` leaves profiles fully visible and spends a credit on a first cold message; `paid_unlocks_and_messaging` also redacts directory cards and gates the opaque `/p/{id}` profile route behind an unlock credit. `null` means the operator has not chosen explicitly, in which case infer it from the published `talent_access` plans: any plan granting profile unlocks means `paid_unlocks_and_messaging`, otherwise `paid_messaging`. The paywall is inert regardless when the board publishes no talent plan. An anonymous viewer has no entitlement read to derive this from, so it ships here rather than only on `me/talent-access`.
* @enum {string|null}
*/
talentAccessModel: "paid_messaging" | "paid_unlocks_and_messaging" | null;
/** @description Employer posting policy. Separate from `features.publicJobSubmission`, which says whether the board takes public submissions at all — this says who may complete one. */
posting: {
/** @description Whether posting a job on this board requires an active membership. When `true`, render the join gate in place of the anonymous post form: the platform rejects a create from a company with no contributing assignment (`membership_required`). Absent board config defaults to `false`. This flag is board policy and is safe to read anonymously; a signed-in employer's own standing rides their company billing options. */
requiresMembership: boolean;
};
analytics: {
ga4MeasurementId: string | null;
gtmId: string | null;
metaPixelId: string | null;
linkedInPartnerId: string | null;
/** @description LinkedIn Campaign Manager conversion ID for account creation (`sign_up`). Null when unset. Used with a direct Insight Tag install (`linkedInPartnerId`); leave null when LinkedIn conversions are fired only via GTM. */
linkedInConversionSignUpId: string | null;
/** @description LinkedIn Campaign Manager conversion ID for successful sign-in (`login`). Null when unset. */
linkedInConversionLoginId: string | null;
/** @description LinkedIn Campaign Manager conversion ID for opening the apply flow (`apply_click`). Null when unset. */
linkedInConversionApplyClickId: string | null;
/** @description LinkedIn Campaign Manager conversion ID for a successful native application (`apply_submit`). Null when unset. */
linkedInConversionApplySubmitId: string | null;
/** @description LinkedIn Campaign Manager conversion ID for job-alert subscription (`job_alert_subscribe`). Null when unset. */
linkedInConversionJobAlertSubscribeId: string | null;
cookieConsentRequired: boolean;
};
/** @description Public AdSense switch, publisher id, and default ad unit from board advertising settings. Applications own placement and may supply bespoke slot ids. Not the hosted slot map or `ads.txt` (`board.seo()`). */
ads: {
/** @description Whether AdSense is turned on for this board (Settings → Advertising). Headless frontends render their own placements only when this is true and `clientId` is a valid `ca-pub-` publisher id. Use `defaultSlotId` for a default ad unit or supply your own Google-issued slot id; applications own placement and geometry. */
enabled: boolean;
/** @description AdSense publisher id (`ca-pub-` + 16 digits), or null when ads are off or the stored value is malformed. Already public on hosted pages as `data-ad-client`. */
clientId: string | null;
/** @description Default Google-issued ad unit id (10 digits). Resolves the enabled jobs:list.footer slot first, then the first enabled valid slot in alphabetical placement-key order. Null when advertising is off, the publisher id is invalid, or no enabled valid slot exists. Frontends may override it per ad unit. */
defaultSlotId: string | null;
};
/** @description Operator-defined custom field definitions keyed by model (currently only `job`). Each key holds that model's definitions in display order. Company and talent keys are added when those models ship. The frontend uses these to render and localize each record's opaque `customFieldValues`. Display-only: not filterable or searchable in v1. */
customFields: {
/** @description This model's custom-field definitions in display order. Empty when the board defines none for the model. */
job: components["schemas"]["CustomFieldDefinition"][];
};
/** @description Built-in job-form field configuration from Settings → Job form (custom fields live on `customFields.job`). The platform ENFORCES these constraints when a job is created — a violation is a 400 — so a posting form that ignores them offers options the server will reject and the employer only finds out on submit. */
jobForm: {
salary: {
/** @description Whether salary is captured on posting forms and shown on public job cards. Absent board config defaults to `true`. */
visible: boolean;
/** @description Whether a posting must carry a salary. Absent board config defaults to `false`. */
required: boolean;
/** @description Salary floor a submitted value must be >= . `null` when unset, and always `null` unless `required` is `true` — a floor is toothless on an optional field, matching hosted. */
minBound: number | null;
/** @description Salary ceiling a submitted value must be <= . `null` when unset, and always `null` unless `required` is `true`. */
maxBound: number | null;
/** @description ISO 4217 subset the board accepts. `null` means no restriction — render the full currency list. Never an empty array. */
allowedCurrencies: string[] | null;
};
seniority: {
/** @description Whether seniority is captured on posting forms. Absent board config defaults to `true`. */
visible: boolean;
/** @description Whether a posting must carry a seniority level. Absent board config defaults to `false`. */
required: boolean;
/** @description Seniority levels the board accepts, in platform order. Always fully resolved — an operator who set no subset gets the complete platform list, so a picker can render straight from this. */
allowedOptions: string[];
};
location: {
/** @description Whether office location is captured on posting forms. Absent board config defaults to `true`. */
visible: boolean;
/** @description ISO country codes office locations are locked to. `null` means any country. Never an empty array. */
allowedCountries: string[] | null;
};
sponsorship: {
/** @description Whether visa sponsorship is captured on posting forms. Absent board config defaults to `true`. */
visible: boolean;
};
workArrangement: {
/** @description Work arrangements the board accepts, fully resolved like `seniority.allowedOptions`. A single entry means the form must collapse the field and pin every submission to that value. */
allowedOptions: string[];
};
employmentType: {
/** @description Employment types the board accepts, fully resolved like `seniority.allowedOptions`. A single entry means the form must collapse the field. */
allowedOptions: string[];
};
};
/** @description Operator-authored contact and social identity (settings › Contact & company details). Extracted from the former `footer` group in 4.0.0: contact is identity data, not layout. Brand/social URLs are sanitized to absolute http(s). */
contact: {
/** @description Public contact email (render as `mailto:`). Operator-set in settings › Contact & company details. */
email: string | null;
/** @description The operating company's registered legal name, or `null` when unset. Use it as the JobPosting `hiringOrganization` name when a job has no company of its own, ahead of the board name — that is the order the hosted board emits, so a headless board produces identical structured data. */
legalName: string | null;
/** @description Company website URL, sanitized to absolute http(s). Null when unset or non-http(s). */
websiteUrl: string | null;
/** @description X (Twitter) profile URL, normalized from the stored handle. */
xUrl: string | null;
/** @description Facebook profile URL, sanitized to absolute http(s). Null when unset or non-http(s). */
facebookUrl: string | null;
/** @description LinkedIn profile URL, sanitized to absolute http(s). Null when unset or non-http(s). */
linkedinUrl: string | null;
};
};
PublicCompaniesSearchBody: {
/** @description Free-text search query matched against company name. Up to 200 characters. */
query?: string;
/** @description Scope the results to companies in a single market (sector), by the market slug. Resolves a board-language or English slug; an unknown slug returns 404. Use `GET /boards/:identifier/companies/markets/:market` to resolve a slug to its canonical form first. */
marketSlug?: string;
/** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
cursor?: string | null;
/** @description A limit on the number of objects to be returned. Limit can range between 1 and 100. */
limit?: number;
/**
* @description The number of companies to skip — the company catalog page offset. Takes precedence over `cursor`; pair with the response `count` to page in parallel. `offset + limit` may not exceed 10,000.
* @example 0
*/
offset?: number;
};
/** @description Public-only links. The admin URL is intentionally omitted on public-board responses. */
PublicCompanyLinks: {
/**
* Format: uri
* @description Canonical public URL for this company on the board, or `null` when no slug is set.
*/
public: string | null;
};
/** @description The company's membership on this board, or `null` when it holds none that is public. Only an ACTIVE assignment on a PUBLISHED plan whose purpose is membership appears here: a company on a private (operator-only) plan reads as `null`, and non-membership purchases — job-posting packs, talent access, services — never appear. Identity only: entitlements, billing state, and expiry are not on the public wire. */
PublicCompanyMembership: {
/** @description The membership plan's `id`. Pass it to `GET /boards/{identifier}/companies?membershipPlanId=` to browse the roster, or join it against the board's plans to render the plan's own copy. */
planId: string;
/** @description The membership plan's current display name — the badge text. Operators rename plans, so treat `planId` as the stable key. */
planName: string;
} | null;
PublicJob: {
/** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
id: string;
/**
* @description String representing the object's type. Objects of the same type share the same value.
* @enum {string}
*/
object: "public_job";
/** @description The job title. */
title: string;
/** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
slug: string | null;
/**
* @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
* @enum {string}
*/
status: "draft" | "published" | "expired" | "archived";
/** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
companyId: string | null;
/**
* @description Employment type of the role, or `null` if not specified.
* @enum {string|null}
*/
employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
/**
* @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
* @enum {string|null}
*/
remoteOption: "on_site" | "hybrid" | "remote" | null;
/**
* @description Seniority level of the role, or `null` if not specified.
* @enum {string|null}
*/
seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
/** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
salaryMin: number | null;
/** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
salaryMax: number | null;
/** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
salaryCurrency: string | null;
/**
* @description Period the salary range is quoted against, or `null` if no salary is specified.
* @enum {string|null}
*/
salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
/** @description Whether the job appears in featured slots on the public board. */
isFeatured: boolean;
/** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
publishedAt: string | null;
/** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
expiresAt: string | null;
/** @description Time at which the job was created. ISO 8601 datetime. */
createdAt: string;
/** @description Time at which the job was last updated. ISO 8601 datetime. */
updatedAt: string;
links: components["schemas"]["PublicJobLinks"];
/** @description Long-form description of the role, or `null` if not specified. */
description: string | null;
/** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
applicationUrl: string | null;
isSponsored: boolean;
/** @enum {string} */
applyAction: "native" | "external_direct" | "gateway_external" | "gateway_native";
/** @description Hierarchical permit selection authored by the board owner. The three `remoteWorkPermit*` and `remoteWorldwide` fields are read-only derived projections. */
remotePermits: {
type: string;
value: string;
}[];
/** @description Read-only: derived from `remotePermits`. `true` only when the authored selection is a single `{type:"worldwide"}` entry. */
remoteWorldwide: boolean | null;
/** @description Hierarchical timezone selection. The flat `remoteAllowedTzOffsets` field below is the read-only derived projection. */
remoteTimezones: {
type: string;
value: string;
plusMinus?: number;
}[];
/** @description Read-only: derived from `remoteTimezones`. UTC hour offsets used by the job-search index. */
remoteAllowedTzOffsets: number[];
/** @description Read-only: derived from `remotePermits` (hierarchical groups fan out to alpha2 sets; subdivisions auto-add the parent country). ISO 3166-1 alpha-2 codes. */
remoteWorkPermitCountryCodes: string[];
/** @description Read-only: derived from `remotePermits` (subdivision entries only). ISO 3166-2 codes. */
remoteWorkPermitSubdivisionCodes: string[];
/**
* @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
* @enum {string}
*/
remoteSponsorship: "yes" | "no" | "unknown";
/** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
/** @description Minimum required experience in months, or `null` if not specified. */
experienceMonths: number | null;
/** @description If `true`, equivalent experience may substitute for the listed education requirements. `null` if not specified. */
experienceInPlaceOfEducation: boolean | null;
/**
* @description Period denominator for `inOfficeFrequency`, or `null` if not specified.
* @enum {string|null}
*/
inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
/** @description How often the candidate must be in-office over `inOfficePeriod`, or `null` if not specified. */
inOfficeFrequency: number | null;
company: components["schemas"]["JobCompany"];
/** @description Physical office locations associated with the job. */
officeLocations: components["schemas"]["JobOfficeLocation"][];
/** @description Resolved job categories (slug + board display name): same shape as the card; names joined server-side. Guaranteed resolvable: every emitted slug resolves via `GET /v1/boards/:identifier/categories/:slug` — consumers never need to re-verify before linking. */
categories: {
slug: string;
name: string;
}[];
/** @description Resolved job skills (slug + board display name). Guaranteed resolvable: every emitted slug resolves via `GET /v1/boards/:identifier/skills/:slug` — consumers never need to re-verify before linking. */
skills: {
slug: string;
name: string;
}[];
/** @description Place ancestor chain (country → region → city) for the breadcrumb; each `{slug,name}` links to `/jobs/locations/:slug`. Source-language. */
placeHierarchy: {
slug: string;
name: string;
}[];
/** @description Opaque, display-only custom-field values, keyed by each field's `key`. Values are the option `key`(s) for select fields, or the raw boolean/number/text otherwise. Resolve labels via the board's `customFields.job` definitions (see `GET /v1/boards/:identifier`). `{}` when the board defines no custom fields. Not filterable or searchable in v1. */
customFieldValues: {
[key: string]: string | string[] | boolean | number;
};
};
PublicJobAlertConfirmation: {
/** @enum {string} */
object: "job_alert_confirmation";
/**
* @description Outcome of the confirmation. Always returned with HTTP 200 so the consumer renders by status (the token may be valid, stale, or unknown).
* @enum {string}
*/
status: "confirmed" | "already_confirmed" | "expired" | "not_found";
};
PublicJobAlertManageResult: {
/** @enum {string} */
object: "job_alert_manage_result";
success: boolean;
};
PublicJobAlertManageState: {
/** @enum {string} */
object: "job_alert_manage_state";
email: string;
confirmed: boolean;
unsubscribed: boolean;
preferences: {
id: string;
label: string | null;
/** @enum {string} */
frequency: "weekly";
isActive: boolean;
filters: {
jobFunctions?: string[];
seniorityLevels?: string[];
remoteOptions?: string[];
placeIds?: string[];
salaryMin?: number | null;
salaryMax?: number | null;
salaryCurrency?: string | null;
};
manageToken: string;
}[];
};
PublicJobAlertResend: {
/** @enum {string} */
object: "job_alert_confirmation_resend";
/**
* @description Always `submitted`. The response is intentionally uniform to prevent email enumeration. If a pending confirmation exists for this email, a confirmation email has been sent (subject to server-side throttle).
* @enum {string}
*/
status: "submitted";
};
PublicJobAlertSubscription: {
/** @enum {string} */
object: "job_alert_subscription";
/**
* @description Always `submitted`. The response is intentionally uniform to prevent email enumeration. If this email isn't already subscribed, a confirmation email has been sent.
* @enum {string}
*/
status: "submitted";
};
PublicJobCard: {
id: string;
/** @enum {string} */
object: "job_card";
slug: string;
title: string;
/**
* Format: date-time
* @description ISO 8601 publish timestamp, or `null` if unpublished.
*/
publishedAt: string | null;
/** @enum {string|null} */
employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
/** @enum {string|null} */
remoteOption: "on_site" | "hybrid" | "remote" | null;
/** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
remoteLocationLabel: string | null;
/** @description Structured twin of `remoteLocationLabel`’s "Worldwide" case: `true` when the job explicitly declares an unrestricted (worldwide) permit, `false` for a constrained remote job, `null` when the job declares no remote scope at all AND for non-remote jobs. A job that declares nothing is unknown, not worldwide — do not treat `null` as unrestricted. Word it from your own catalog instead of matching the board-language label string. */
remoteWorldwide: boolean | null;
/** @description ISO 3166-1 alpha-2 codes the remote permit selection covers (derived expansion, mirroring the job detail field of the same name). Empty for worldwide/unconstrained and non-remote jobs. */
remoteWorkPermitCountryCodes: string[];
salaryMin: number | null;
salaryMax: number | null;
salaryCurrency: string | null;
salaryTimeframe: string | null;
isFeatured: boolean;
/** @description True when this listing is a Forager CPC / partner-feed ad persisted on the board. */
isSponsored: boolean;
/** @description Plain-text card teaser derived from the job description (HTML stripped, first sentence / word-boundary cut). `null` when there is nothing honest to show. Always present — independent of the `?fields=+description` opt-in for the long-form HTML body. Prefer this over requesting `+description` for list/card renders. */
summary: string | null;
locationLabel: string | null;
/** @description Embedded company summary, or `null` if none is attached. */
company: {
slug: string;
name: string;
logoUrl: string | null;
} | null;
/** @description Job categories (slug + board display name). Guaranteed resolvable: every emitted slug resolves via `GET /v1/boards/:identifier/categories/:slug`. */
categories: {
slug: string;
name: string;
}[];
/** @description Job skills (slug + board display name). Guaranteed resolvable: every emitted slug resolves via `GET /v1/boards/:identifier/skills/:slug`. */
skills: {
slug: string;
name: string;
}[];
links: {
/**
* Format: uri
* @description Canonical public URL for this job, or `null` when no stable URL can be assembled.
*/
public: string | null;
};
/** @description Long-form description (HTML), or `null`. Present ONLY when requested via `?fields=+description`; absent on the default slim card. */
description?: string | null;
};
/** @description Public-only links. The admin URL is intentionally omitted on public-board responses. */
PublicJobLinks: {
/**
* Format: uri
* @description Canonical public URL for this job, or `null` when the job has no slug or no associated company slug (so a stable URL cannot be assembled).
*/
public: string | null;
};
PublicPlace: {
/** @enum {string} */
object: "place";
/** @description Stable place identity (locations-tree edge endpoint). */
id: string;
/** @description Parent place's `id`; `null` for a root place. */
parentId: string | null;
/** @description Public slug (links to `/jobs/locations/:slug`); `null` if unslugged. */
slug: string | null;
name: string;
placeType: string;
countryCode: string | null;
regionCode: string | null;
/** @description Live published-job count for this place. */
jobCount: number;
};
PublicSearchJobsBody: {
/** @description Free-text search query matched against job title and description. Up to 200 characters. */
query?: string;
/**
* @description Result ordering. `relevance` (default) ranks by search relevance with featured jobs first; `newest` orders by publish date and `salary_high` by salary (no-salary jobs last). Any explicit sort unpins featured jobs.
* @enum {string}
*/
sort?: "relevance" | "newest" | "salary_high";
/** @description Optional faceted filters to narrow search results. Multi-value filters match jobs in any of the supplied values; range filters accept `gte` and `lte` bounds. */
filters?: {
/** @description Only return jobs at any of the given company IDs. Up to 10 values. */
companyId?: string[];
/** @description Company slugs (the public URL identity). Up to 10. Resolved server-side; unknown slugs are dropped. Combined with `companyId` as a union. If the provided company filter resolves to no known companies, the result is empty. */
companySlug?: string[];
/** @description Only return jobs with any of the given remote-work options. Up to 10 values. */
remoteOption?: ("on_site" | "hybrid" | "remote")[];
/** @description Only return jobs with any of the given employment types. Up to 10 values. */
employmentType?: ("full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other")[];
/** @description Only return jobs at any of the given seniority levels. Up to 10 values. */
seniority?: ("entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive")[];
/** @description Range filter on the job's `publishedAt` timestamp. */
publishedAt?: {
/**
* Format: date-time
* @description Only return jobs published at or after this ISO 8601 datetime.
*/
gte?: string;
/**
* Format: date-time
* @description Only return jobs published at or before this ISO 8601 datetime.
*/
lte?: string;
};
/** @description Only return jobs near the place with this slug (geo radius search). Unresolvable slugs are ignored. */
location?: string;
/** @description Search radius in kilometres around `location` (10–250; default 50). Ignored without `location`. */
radius?: number;
};
/** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
cursor?: string;
/**
* @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
* @example 20
*/
limit?: number;
/**
* @description The number of jobs to skip: the job catalog page offset. Takes precedence over `cursor`. `offset + limit` may not exceed 10,000.
* @example 0
*/
offset?: number;
};
PublicTaxonomyResolution: {
/** @enum {string} */
object: "taxonomy_resolution";
/** @enum {string} */
type: "category" | "skill" | "place" | "market";
/** @description Immutable English source slug — the semantic-search key. */
sourceSlug: string;
/** @description Board-language URL slug (the `` target). */
canonicalSlug: string;
/** @description Board-language display name. */
displayName: string;
/** @description The canonical slug to emit a 308 redirect to when the inbound slug differs; `null` otherwise. */
redirectTo: string | null;
geo: components["schemas"]["TaxonomyGeo"];
};
PublicTaxonomyTerm: {
/** @enum {string} */
object: "taxonomy_term";
/** @description Stable taxonomy entity ID. */
id: string;
/** @enum {string} */
type: "category" | "skill";
/** @description Current source-locale slug used by job search; old slugs may remain aliases. */
sourceSlug: string;
/** @description Board-language canonical URL slug. */
canonicalSlug: string;
/** @description Board-language name with source-name fallback. */
displayName: string;
/** @description Live published-job count for this term on the board. Maintained as jobs publish and expire — not a tally of the current list page. */
jobCount: number;
};
PublicVerifyBoardPasswordBody: {
/** @description The board password. */
password: string;
};
ReadReceipt: {
/** @enum {string} */
object: "read_receipt";
/** Format: date-time */
markedAt: string;
};
RecommendedJob: {
/** @enum {string} */
object: "recommended_job";
job: components["schemas"]["PublicJobCard"];
};
RecommendedTalent: {
/** @enum {string} */
object: "recommended_talent";
candidate: components["schemas"]["TalentDirectoryEntry"];
};
RedirectResolution: {
/** @enum {string} */
object: "redirect_resolution";
path: string;
/** @description The redirect target (board-relative), or `null` when no redirect matches. The consumer 308s to `target`, or 404s when `null`. */
target: string | null;
};
RemotePermitTaxonomyEntry: {
/** @description Discriminator. One of: `worldwide`, `world_region`, `continent`, `region`, `subregion`, `custom`, `country`, `subdivision`. */
type: string;
/** @description Canonical value for the type. ISO 3166-1 alpha-2 for `country`, ISO 3166-2 for `subdivision`, etc. */
value: string;
/** @description Human-readable display label. */
label: string;
};
ReorderPipelineStagesBody: {
/** @description The job whose stages are reordered. */
jobId: string;
/** @description Every stage id of the job, in the new order. */
orderedStageIds: string[];
};
ReplyBody: {
body: string;
};
ReportBody: {
/** @enum {string} */
reason: "spam" | "harassment" | "misrepresentation" | "other";
freeText?: string;
};
RequestEmailChangeBody: {
/** Format: email */
email: string;
};
Resume: {
/** @enum {string} */
object: "resume";
/**
* @description Async parse state; poll GET /me/resume until parsed or failed.
* @enum {string|null}
*/
parseStatus: "parsing" | "parsed" | "failed" | null;
parseFailureReason: string | null;
/** Format: date-time */
parsedAt: string | null;
keepResumeOnFile: boolean | null;
hasResumeOnFile: boolean;
file: {
/** @description Short-lived signed download URL. */
url: string;
contentType: string;
sizeBytes: number;
} | null;
};
SalaryCompanyIndexItem: {
/** @enum {string} */
object: "salary_company";
companySlug: string;
companyName: string;
logoPath: string | null;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
currency: string;
};
SalaryLocationIndexItem: {
/** @enum {string} */
object: "salary_location";
placeSlug: string;
placeName: string;
/** @description Slug of the parent place; `null` for a top-level node. */
parentSlug: string | null;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
};
SalarySkillIndexItem: {
/** @enum {string} */
object: "salary_skill";
slug: string;
name: string;
avgSalaryMin: number;
avgSalaryMax: number;
p25SalaryMin: number;
p75SalaryMax: number;
jobCount: number;
currency: string;
};
SalaryTitleIndexItem: {
/** @enum {string} */
object: "salary_title";
slug: string;
name: string;
avgSalaryMin: number;
avgSalaryMax: number;
p25SalaryMin: number;
p75SalaryMax: number;
jobCount: number;
currency: string;
};
/** @description Deprecated. Prefer public plans with purpose employer_service and pricingMode contact. */
SalesLedPlan: {
/** @enum {string} */
object: "sales_led_plan";
id: string;
name: string;
description: string;
/** @description Display price text, e.g. "Contact us". */
priceText: string;
ctaText: string;
/** @description The CTA target: a URL, mailto:, or tel: link. */
ctaDestination: string;
featuredBullets: string[];
displayOrder: number;
};
SaveJobBody: {
jobId: string;
};
SavedJob: {
/** @description Saved-job row ID. */
id: string;
/** @enum {string} */
object: "saved_job";
/** @description The saved job id. Also the DELETE path key. */
jobId: string;
/** Format: date-time */
savedAt: string;
job: components["schemas"]["PublicJobCard"];
};
SendWorkEmailBody: {
/** Format: email */
workEmail: string;
};
SitemapEntry: {
/** @enum {string} */
object: "sitemap_entry";
/** @description Board-relative path, always starting with `/`. Prefix it with your own origin to build the absolute URL — the API never returns the hosted origin. */
path: string;
/** @description ISO 8601 timestamp of the entry, when one is known. */
lastModified?: string;
};
SkillLocationSalary: {
/** @enum {string} */
object: "skill_location_salary";
skillSourceSlug: string;
skillCanonicalSlug: string;
locationSourceSlug: string;
locationCanonicalSlug: string;
skillName: string;
placeName: string;
countryCode: string;
adminLevel: string;
overallSalary: {
avgMin: number;
avgMax: number;
p25Min: number | null;
p75Max: number | null;
jobCount: number;
} | null;
bySeniority: {
seniority: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
childLocations: {
placeSlug: string;
placeName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
childLocationsByRegion: {
regionName: string;
regionSlug: string;
cities: {
placeSlug: string;
placeName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
}[];
otherLocations: {
placeSlug: string;
placeName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
topSkills: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
skillSlug: string;
skillName: string;
}[];
topTitles: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
categorySlug: string;
categoryName: string;
}[];
boardSkillAvgMin: number | null;
boardSkillAvgMax: number | null;
currency: string;
};
SkillLocationsIndex: {
/** @enum {string} */
object: "skill_locations_index";
sourceSlug: string;
canonicalSlug: string;
skillName: string;
currency: string;
locations: components["schemas"]["SalaryLocationIndexItem"][];
};
SkillSalaryDetail: {
/** @enum {string} */
object: "skill_salary_detail";
/** @description Immutable English source slug: the salary-stats key. */
sourceSlug: string;
/** @description Board-language canonical URL slug: the starter 308 target. */
canonicalSlug: string;
skillName: string;
overallSalary: {
avgMin: number;
avgMax: number;
medianMin: number;
medianMax: number;
p25Min: number;
p75Max: number;
jobCount: number;
} | null;
bySeniority: {
seniority: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
boardAvgMin: number | null;
boardAvgMax: number | null;
diffPercent: number | null;
}[];
topCompanies: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
companySlug: string;
companyName: string;
logoPath: string | null;
}[];
topLocations: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
placeName: string;
placeSlug: string;
countryCode: string;
}[];
topTitles: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
categorySlug: string;
categoryName: string;
}[];
relatedSkills: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
skillSlug: string;
skillName: string;
}[];
totalLocationCount: number;
boardOverallAvgMin: number | null;
boardOverallAvgMax: number | null;
boardMedianMin: number | null;
boardMedianMax: number | null;
currency: string;
};
SourcedCandidate: {
id: string;
/** @enum {string} */
object: "sourced_candidate";
candidate: components["schemas"]["TalentDirectoryEntry"];
sourcedAt: number;
sourcedBy: string;
};
StartAboutApplicationBody: {
applicationId: string;
body: string;
};
StartConversationBody: {
candidateBoardUserId: string;
body: string;
/** @description Optional job id. When set, this send is from that job pipeline and may auto-advance Shortlisted to Contacted. */
job?: string;
} | {
candidateHandle: string;
body: string;
/** @description Optional job id. When set, this send is from that job pipeline and may auto-advance Shortlisted to Contacted. */
job?: string;
};
SuggestResult: {
/** @enum {string} */
object: "suggest_result";
/** @description The trimmed query string that produced these suggestions. */
query: string;
/** @description Interleaved company, market, taxonomy-term, blog-post, and tag suggestions. Order is server-ranked; clients must not re-sort. When `types` is set, only the requested kinds appear and `limit` applies after that filter. */
items: components["schemas"]["SuggestionItem"][];
};
SuggestionItem: components["schemas"]["CompanySuggestion"] | components["schemas"]["MarketSuggestion"] | components["schemas"]["TermSuggestion"] | components["schemas"]["PostSuggestion"] | components["schemas"]["TagSuggestion"];
TagSuggestion: {
/** @enum {string} */
object: "suggestion";
/**
* @description discriminator enum property added by openapi-typescript
* @enum {string}
*/
type: "tag";
/** @description Stable tag identity (source slug; tags are slug-keyed). */
id: string;
/** @description Public blog tag URL slug. */
slug: string;
/** @description Tag display name. */
name: string;
};
TalentAccess: {
/** @enum {string} */
object: "talent_access";
/** @description Whether the viewer has an approved company membership on this board. */
isEmployer: boolean;
/** @description Whether this board sells talent access (a public `talent_access` plan exists). When `false` the talent surfaces are not credit-gated for employers. */
paywallActive: boolean;
/** @description The CTA answer: the viewer is an approved employer AND either the board has no talent paywall or one of their companies holds an active talent_access subscription or a succeeded credit pack. Always `false` for candidates; anonymous viewers get 401. Never cached. */
hasTalentAccess: boolean;
/** @description True when any active talent_access subscription carries the unlimited profile-unlock sentinel on its feature snapshot. */
hasUnlimitedUnlocks: boolean;
/**
* @description `none` when the paywall is off. Otherwise the board charging model: paid messaging only, or paid unlocks and messaging. Inferred from public plan unlock credits when the stored config is unset.
* @enum {string}
*/
accessModel: "none" | "paid_messaging" | "paid_unlocks_and_messaging";
/** @description The approved company to charge checkout/unlock against when the viewer has exactly one membership. `null` when they have none or more than one (pass `companyId` on write). */
companyId: string | null;
/** @description Summed finite remaining profile-unlock credits across the viewer’s companies. `0` when unlimited or when they hold no spendable credits. */
unlockCreditsRemaining: number;
/** @description Summed finite remaining first-message credits. `0` when unlimited or when they hold no spendable credits. */
messageCreditsRemaining: number;
/** @description True when any active talent_access subscription carries the unlimited message-credit sentinel. */
hasUnlimitedMessages: boolean;
};
TalentAccessCheckoutBody: {
planId: string;
returnPath: string;
/** @enum {string} */
colorMode: "light" | "dark";
companyId?: string;
};
TalentAccessClaim: {
/** @enum {string} */
object: "talent_access_claim";
assignmentId: string;
alreadyClaimed: boolean;
};
TalentAccessClaimBody: {
planId: string;
companyId?: string;
};
TalentAccessUpgradeBody: {
planId: string;
companyId?: string;
};
TalentCandidateAccess: {
/** @enum {string} */
object: "talent_candidate_access";
candidateId: string;
companyId: string | null;
alreadyUnlocked: boolean;
unlockCreditsRemaining: number;
messageCreditsRemaining: number;
hasUnlimitedUnlocks: boolean;
hasUnlimitedMessages: boolean;
hasActiveTalentSubscription: boolean;
};
TalentDirectoryEntry: {
/** @enum {string} */
object: "talent_directory_entry";
/** @description The candidate’s board-user id. When a public talent_access plan exists, directory cards link to the opaque `/p/{id}` route so profile unlocks can apply. The named `/p/{handle}` route is the share bypass. */
id: string;
handle: string | null;
displayName: string | null;
headline: string | null;
location: string | null;
avatarUrl: string | null;
/** @description Plain-text card teaser derived from `bio` (HTML stripped, first sentence / word-boundary cut). `null` when there is nothing honest to show. Prefer this over `bio` for directory/card renders; cards still lead with `headline` when present. */
summary: string | null;
/**
* @deprecated
* @description Long-form candidate bio. **Deprecated on directory entries** — prefer `summary` for card teasers. Still the full prose on the talent profile detail (`GET …/talent/{handle}`).
*/
bio: string | null;
jobSearchStatus: string | null;
skills: string[];
experiences: {
title: string;
companyName: string;
startDate: string;
endDate: string | null;
}[];
education: {
institutionName: string;
startDate: string | null;
endDate: string | null;
}[];
};
TalentList: {
id: string;
/** @enum {string} */
object: "talent_list";
name: string;
filters: components["schemas"]["TalentListFilters"];
jobId: string | null;
createdBy: string;
createdAt: number;
updatedAt: number;
};
TalentListFilters: {
q?: string;
skill?: string;
/** @enum {string} */
jobSearchStatus?: "actively_looking" | "open_to_offers" | "not_looking";
languages?: string[];
openToRelocate?: boolean;
place?: string;
/** @enum {string} */
sort?: "relevance" | "newest";
seniority?: string;
permitCountry?: string;
interestedRole?: string;
};
TalentProfile: {
/** @enum {string} */
object: "talent_profile";
/** @description The candidate’s board-user id. The opaque talent-paywall route key (`/p/{id}`); `handle` is the named-share bypass. */
id: string;
handle: string | null;
displayName: string | null;
headline: string | null;
location: string | null;
bio: string | null;
avatarUrl: string | null;
/** @description The candidate job-search status, or `null` when it is set to employers-only (an anonymous caller is not an employer). */
jobSearchStatus: string | null;
experiences: {
title: string;
companyName: string;
companyUrl: string | null;
/** @description Absolute logo URL for the company, resolved from `companyUrl` the same way the hosted profile renders it; `null` when the company has no usable website. Render a monogram/initials fallback when `null` (and on image error: the URL 404s when the brand has no icon). */
companyLogoUrl: string | null;
location: string | null;
employmentType: string | null;
locationType: string | null;
foundVia: string | null;
/** @description Start month, `YYYY-MM`. */
startDate: string;
/** @description End month `YYYY-MM`, or `null` for a current role. */
endDate: string | null;
description: string | null;
/** @description Skills the candidate applied in this role. */
experienceSkills: string[];
}[];
education: {
institutionName: string;
institutionUrl: string | null;
/** @description Absolute logo URL for the institution, resolved from `institutionUrl` the same way the hosted profile renders it; `null` when the institution has no usable website. Render a monogram/initials fallback when `null` (and on image error). */
institutionLogoUrl: string | null;
degree: string | null;
fieldOfStudy: string | null;
grade: string | null;
activitiesAndSocieties: string | null;
startDate: string | null;
endDate: string | null;
description: string | null;
}[];
skills: {
name: string;
/** @description Reference to the canonical skill taxonomy, when matched. */
jobSkillId: string | null;
}[];
languages: {
name: string;
proficiency: string;
}[];
};
TalentUnlock: {
/** @enum {string} */
object: "talent_unlock";
alreadyUnlocked: boolean;
unlockCreditsRemaining: number | null;
};
TalentUnlockBody: {
candidateId: string;
companyId?: string;
};
TalentUpgrade: {
/** @enum {string} */
object: "talent_upgrade";
/** @enum {boolean} */
ok: true;
};
/** @description Geo for place resolutions; `null` for category/skill. */
TaxonomyGeo: {
lat: number | null;
lng: number | null;
countryCode: string | null;
regionCode: string | null;
region: string | null;
city: string | null;
locality: string | null;
placeType: string | null;
} | null;
TermSuggestion: {
/** @enum {string} */
object: "suggestion";
/**
* @description discriminator enum property added by openapi-typescript
* @enum {string}
*/
type: "term";
/**
* @description Whether this taxonomy term is a category or a skill.
* @enum {string}
*/
termType: "category" | "skill";
/** @description Stable taxonomy entity ID. */
id: string;
/** @description Current source-locale slug used by job search; old slugs may remain aliases. */
sourceSlug: string;
/** @description Board-language canonical URL slug. */
canonicalSlug: string;
/** @description Board-language name with source-name fallback. */
displayName: string;
};
TitleLocationSalary: {
/** @enum {string} */
object: "title_location_salary";
categorySourceSlug: string;
categoryCanonicalSlug: string;
locationSourceSlug: string;
locationCanonicalSlug: string;
categoryName: string;
placeName: string;
countryCode: string;
adminLevel: string;
overallSalary: {
avgMin: number;
avgMax: number;
p25Min: number | null;
p75Max: number | null;
jobCount: number;
} | null;
bySeniority: {
seniority: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
childLocations: {
placeSlug: string;
placeName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
childLocationsByRegion: {
regionName: string;
regionSlug: string;
cities: {
placeSlug: string;
placeName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
}[];
otherLocations: {
placeSlug: string;
placeName: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
}[];
topSkills: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
skillSlug: string;
skillName: string;
}[];
topTitles: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
categorySlug: string;
categoryName: string;
}[];
boardCategoryAvgMin: number | null;
boardCategoryAvgMax: number | null;
currency: string;
};
TitleLocationsIndex: {
/** @enum {string} */
object: "title_locations_index";
sourceSlug: string;
canonicalSlug: string;
categoryName: string;
currency: string;
locations: components["schemas"]["SalaryLocationIndexItem"][];
};
TitleSalaryDetail: {
/** @enum {string} */
object: "title_salary_detail";
/** @description Immutable English source slug: the salary-stats key. */
sourceSlug: string;
/** @description Board-language canonical URL slug: the starter 308 target. */
canonicalSlug: string;
categoryName: string;
overallSalary: {
avgMin: number;
avgMax: number;
p25Min: number;
p75Max: number;
jobCount: number;
} | null;
bySeniority: {
seniority: string;
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
boardAvgMin: number | null;
boardAvgMax: number | null;
boardMedianMin: number | null;
boardMedianMax: number | null;
boardP25Min: number | null;
boardP75Min: number | null;
boardP25Max: number | null;
boardP75Max: number | null;
diffPercent: number | null;
}[];
topCompanies: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
companySlug: string;
companyName: string;
logoPath: string | null;
}[];
topLocations: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
placeName: string;
placeSlug: string;
countryCode: string;
}[];
topSkills: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
skillSlug: string;
skillName: string;
}[];
relatedTitles: {
avgSalaryMin: number;
avgSalaryMax: number;
jobCount: number;
categorySlug: string;
categoryName: string;
}[];
totalLocationCount: number;
boardOverallAvgMin: number | null;
boardOverallAvgMax: number | null;
boardMedianMin: number | null;
boardMedianMax: number | null;
boardP25Min: number | null;
boardP75Max: number | null;
currency: string;
};
UnreadCount: {
/** @enum {string} */
object: "unread_count";
count: number;
};
UnsubscribeBody: {
boardUserId: string;
/** @enum {string} */
channel: "messageEmails" | "applicationEmails" | "recommendedJobEmails";
token: string;
};
UpdateApplicationFactsBody: {
candidateName?: string;
/** Format: email */
candidateEmail?: string;
candidateHeadline?: string;
candidateLocation?: string;
coverNote?: string;
};
UpdateCandidateProfileBody: {
displayName?: string;
bio?: string;
handle?: string;
headline?: string;
location?: string;
countryCode?: string | null;
/** @enum {string} */
profileVisibility?: "hidden" | "logged_in_only" | "public";
/** @enum {string} */
jobSearchStatus?: "actively_looking" | "open_to_offers" | "not_looking";
/** @enum {string} */
jobSearchStatusVisibleTo?: "everyone" | "employers_only";
openToRelocate?: boolean;
};
UpdateCompanyMemberRoleBody: {
/** @enum {string} */
role: "admin" | "member";
};
UpdateEducationBody: {
institutionName?: string;
institutionUrl?: string;
degree?: string;
fieldOfStudy?: string;
grade?: string;
activitiesAndSocieties?: string;
startDate?: string;
endDate?: string;
description?: string;
sortOrder?: number;
};
UpdateEmployerCompanyBody: {
name?: string;
description?: string;
website?: string;
summary?: string;
xUrl?: string;
linkedinUrl?: string;
facebookUrl?: string;
};
UpdateExperienceBody: {
title?: string;
companyName?: string;
startDate?: string;
companyUrl?: string;
location?: string;
employmentType?: string;
locationType?: string;
foundVia?: string;
endDate?: string;
description?: string;
sortOrder?: number;
};
UpdateLanguagesBody: {
languages: {
name: string;
proficiency: string;
}[];
};
UpdateNotificationPreferenceBody: {
/** @enum {string} */
channel: "messageEmails" | "applicationEmails" | "recommendedJobEmails";
subscribed: boolean;
};
UpdatePasswordBody: {
currentPassword: string;
/** @description Minimum 8 characters. */
newPassword: string;
};
UpdatePipelineStageBody: {
label?: string;
hidden?: boolean;
};
UpdateSkillsBody: {
skills: string[];
};
UpdateTalentListBody: {
name?: string;
filters?: components["schemas"]["TalentListFilters"];
job?: string | unknown;
};
VerifyEmailOtpBody: {
code: string;
};
};
responses: never;
parameters: never;
requestBodies: never;
headers: never;
pathItems: never;
}
type Schemas = components['schemas'];
export type { Schemas as S, components as c };