Recipe catalog / job-post-facets
Label what a job posting states
Which of these does posting state: salary or range, work location, remote policy, experience level, required qualifications?
You check job postings for completeness before publishing, or normalize scraped postings into structured fields.
Explore this recipe interactively ยท Source and implementation guide
Use job-post-facets in TypeScript
Install with npm install jev-recipes. Requires Node.js 22.9 or newer and ES modules. Set TYPESAFE_API_KEY in your server environment for live calls, which send input to TypeSafe and use API quota. See the installation guide.
import { jobPostFacets } from 'jev-recipes/job-post-facets';
const result = await jobPostFacets({
"posting": "Senior Backend Engineer, Berlin (hybrid, 2 days in office). EUR 85,000 to 105,000 plus equity. You have 5+ years building distributed systems in Go or Java and have run PostgreSQL in production. Fluent English required.",
"minConfidence": 0.8
});
console.log(result);
Input contract
| Field | Type | Needed |
|---|---|---|
| posting | string | Required |
| minConfidence | number | Optional |
Full input and result schemas
{
"input": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"posting": {
"type": "string"
},
"minConfidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"posting"
]
},
"result": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"model": {
"type": "string"
},
"usage": {
"type": "object",
"properties": {
"input_tokens": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"output_tokens": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"input_tokens",
"output_tokens"
],
"additionalProperties": false
},
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"detected": {
"type": "array",
"items": {
"type": "string",
"enum": [
"statesSalary",
"statesLocation",
"statesRemotePolicy",
"statesExperienceLevel",
"statesQualifications"
]
}
},
"labels": {
"type": "object",
"properties": {
"statesSalary": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesLocation": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesRemotePolicy": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesExperienceLevel": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesQualifications": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
}
},
"required": [
"statesSalary",
"statesLocation",
"statesRemotePolicy",
"statesExperienceLevel",
"statesQualifications"
],
"additionalProperties": false
}
},
"required": [
"model",
"usage",
"status",
"detected",
"labels"
],
"additionalProperties": false
}
}Saved example result
This hand-authored response demonstrates the contract. It is not a model accuracy measurement. Run it without an API key: npx jev-recipes demo job-post-facets.
{
"model": "demo-fixture",
"usage": {
"input_tokens": 0,
"output_tokens": 0
},
"status": "ready",
"detected": [
"statesSalary",
"statesLocation",
"statesRemotePolicy",
"statesExperienceLevel",
"statesQualifications"
],
"labels": {
"statesSalary": {
"status": "ready",
"verdict": "present",
"probability": 0.97,
"confidence": 0.97
},
"statesLocation": {
"status": "ready",
"verdict": "present",
"probability": 0.96,
"confidence": 0.96
},
"statesRemotePolicy": {
"status": "ready",
"verdict": "present",
"probability": 0.94,
"confidence": 0.94
},
"statesExperienceLevel": {
"status": "ready",
"verdict": "present",
"probability": 0.95,
"confidence": 0.95
},
"statesQualifications": {
"status": "ready",
"verdict": "present",
"probability": 0.93,
"confidence": 0.93
}
}
}
Evaluation evidence
No verified live accuracy measurement is available. Evaluate representative cases before using this decision in your workflow.
Use the evaluation guide to measure this decision on your own labeled cases.
Limitations
- Labels report that a facet is stated, not its value. Extract the salary or location in code.
- Labels are independent, so a posting can carry several or none.
- Does not judge whether the stated details are lawful or accurate for the jurisdiction.
Related recipes
- clarify: Use clarify to list which required details are missing or ambiguous in free text.
- requirement-testability: Use requirement-testability to check whether a stated qualification can be verified.