Technologies on each job

Add a graded list of technologies to every posting a search returns, and tell required skills from nice-to-haves.

A job board wants to show "Required: Python, Snowflake. Nice to have: dbt" on every listing. A recruiting tool wants to match candidates on what a role actually requires, not on every word in the description. Send include_technologies: true on a job search and every posting carries a technologies list, each entry graded by how strongly the posting asks for it.

Beta. technologies is empty on a posting until it has been extracted, so treat an empty list as "not known yet" rather than "none".

Request

curl https://api.jobspipe.dev/v1/jobs/search \
  -H "Authorization: Bearer jp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "job_title_or": ["data engineer"],
    "job_country_code_or": ["GB"],
    "posted_at_max_age_days": 7,
    "include_technologies": true,
    "limit": 25
  }'
import requests

resp = requests.post(
    "https://api.jobspipe.dev/v1/jobs/search",
    headers={"Authorization": "Bearer jp_live_your_key_here"},
    json={
        "job_title_or": ["data engineer"],
        "job_country_code_or": ["GB"],
        "posted_at_max_age_days": 7,
        "include_technologies": True,
        "limit": 25,
    },
).json()

for job in resp["data"]:
    required = [t["name"] for t in job["technologies"] if t["strength"] == "required"]
    preferred = [t["name"] for t in job["technologies"] if t["strength"] == "preferred"]
    print(job["job_title"], "-", job["company"])
    print("  Required:", ", ".join(required) or "-")
    print("  Nice to have:", ", ".join(preferred) or "-")
const resp = await fetch("https://api.jobspipe.dev/v1/jobs/search", {
  method: "POST",
  headers: {
    Authorization: "Bearer jp_live_your_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    job_title_or: ["data engineer"],
    job_country_code_or: ["GB"],
    posted_at_max_age_days: 7,
    include_technologies: true,
    limit: 25,
  }),
}).then((r) => r.json());

for (const job of resp.data) {
  const names = (strength) =>
    job.technologies.filter((t) => t.strength === strength).map((t) => t.name);
  console.log(job.job_title, "-", job.company);
  console.log("  Required:", names("required").join(", ") || "-");
  console.log("  Nice to have:", names("preferred").join(", ") || "-");
}

include_technologies does not change which jobs match. It only adds the field.

Response

200 OK
{
  "metadata": {
    "next_cursor": "eyJwIjoiMjAyNi0wOS0yMiAwMDowMDowMCIsImkiOiI5MTIzNDUifQ",
    "credits_charged": 43,
    "jobs_already_paid": 2,
    "technologies_credits_charged": 20,
    "technologies_already_paid": 1,
    "credits_remaining": 24339,
    "credits_allowance": 25000
  },
  "data": [
    {
      "id": "912345",
      "job_title": "Senior Data Engineer",
      "company": "Northwind Labs",
      "country_code": "GB",
      "technologies": [
        {
          "slug": "snowflake",
          "name": "Snowflake",
          "kind": "product",
          "category": "Databases",
          "parent_category": "Software and tools",
          "logo": null,
          "strength": "required",
          "confidence": "medium",
          "sections": ["requirements"],
          "in_title": false,
          "terms": ["snowflake"],
          "terms_cs": []
        },
        {
          "slug": "dbt",
          "name": "dbt",
          "kind": "product",
          "category": "",
          "parent_category": "",
          "logo": null,
          "strength": "preferred",
          "confidence": "low",
          "sections": ["requirements"],
          "in_title": false,
          "terms": ["dbt"],
          "terms_cs": []
        }
      ]
    }
  ]
}

The list is sorted required, then preferred, then mentioned; within each, confidence high to low; then by name. So the first entries are always the ones the employer cares about most.

Strength and confidence

Two separate grades answer two separate questions.

strength: how much does the employer want it?

ValueMeaning
requiredThe posting asks for it.
preferredA nice-to-have.
mentionedNamed without being asked for, for example "our stack includes...".

confidence: how sure are we that the posting names it?

ValueMeaning
highIndependent checks agree the posting names it.
mediumIt is required, or it is in the title.
lowOtherwise.

For matching candidates, a good rule is to use required entries as must-haves and preferred entries as a ranking boost. Show mentioned entries as context only.

Highlight the mention in the description

terms holds case-insensitive text forms and terms_cs holds case-sensitive ones (for short names like Go or R, where a case-insensitive match would find every "go" in the text). Use them to highlight where the posting names each technology:

import re

def highlight(description: str, tech: dict) -> str:
    for term in tech["terms"]:
        description = re.sub(re.escape(term), lambda m: f"**{m.group(0)}**", description, flags=re.I)
    for term in tech["terms_cs"]:
        description = re.sub(rf"\b{re.escape(term)}\b", f"**{term}**", description)
    return description

sections tells you which part of the posting it came from, and in_title is true when the job title itself names it.

Credits

Each returned job that names at least one technology costs 1 extra credit on top of the job's own credit, once per job per calendar month (UTC). Fetching the same job's technologies again that month is free, and a job with an empty list costs nothing extra.

The response reports that part of the bill on its own: metadata.technologies_credits_charged is what the technologies cost in this call, and metadata.technologies_already_paid counts jobs whose technologies you had already paid for. Both are included in metadata.credits_charged. In the example above, 23 new jobs cost 23 credits and 20 of them had technologies, for 43 in total.

If you only need to know which technologies a posting names, without grades, technology_slugs is on every job at no extra cost. Prefer technologies whenever the difference between required and mentioned matters.

On this page