JobFrame · API
Map a roster to JobFrame in one call.
Resolve a messy title, compute the coordinate distance between two canonical profiles, or bulk-map a whole roster — three metered endpoints on one authenticated surface. Every payload shape and price on this page is read from the live route handlers, not hand-typed. Full recipe set (CSV quickstart, MCP variant, billing detail): docs/jobframe/API-ADOPTION-KIT.md. How the matching itself works: /jobframe/matching.
The three meters
| Meter | Endpoint | Price | Free |
|---|---|---|---|
| metered-resolve | GET /api/v1/resolve | $0.01 / resolve (1,000/mo free) | 1,000/mo per IP |
| metered-match | GET /api/v1/match | $0.05 / match | none — key required |
| metered-bulk-map | POST /api/v1/bulk-map | $0.02 / employee-row | none — key required |
The Developer plan is $99.00/mo with 25,000 included calls — only resolve draws down that allowance; match and bulk-map meter from call/row 1 regardless of plan. It's the only way to get a key today — buy it via Stripe Checkout, which mints your pa_… key on completion.
Auth & host
Send Authorization: Bearer pa_<your-key>. No key → free tier (resolve only, up to the ceiling above); an unkeyed match or bulk-map call returns 402 with a Stripe Checkout link so an agent can buy inline. Call the toolbox's own production host — not jobframe.global (its proxy rewrite only touches page routes; /api/* is excluded from that matcher on purpose):
export TOOLBOX_BASE_URL=https://people-analytics-toolbox.vercel.app
export PA_API_KEY=pa_...Resolve one title
Free ≤ 1,000/mo per IP unkeyed, then $0.01 / resolve (1,000/mo free). Deterministic alias/fuzzy match against the JobFrame canon — no LLM in the serving path.
curl -sS "$TOOLBOX_BASE_URL/api/v1/resolve?title=Senior%20Software%20Engineer" \
-H "Authorization: Bearer $PA_API_KEY"{
"contract": "pa-api/v1",
"entitlement": { "plan": "developer", "keyPrefix": "pa_AbCdEfGh1234" },
"usage": { "units": 1, "unit": "call", "billedCents": 1 },
"data": {
"normalizedTitle": "senior software engineer",
"recommendedAction": "auto_accept",
"candidates": [
{ "profileKey": "SWE.GEN.P5", "rank": 1, "confidence": 0.94,
"confidenceBand": "high", "basis": "alias_match", "requiresReview": false }
],
"explainer": "/jobframe/matching"
}
}Distance between two profiles
Keyed only ($0.05 / match). Pairwise (a+b) or nearest-neighbors (profileKey), over structural | content | pay | semantic coordinate editions.
curl -sS "$TOOLBOX_BASE_URL/api/v1/match?a=SWE.GEN.P5&b=SWE.GEN.P6&space=structural" \
-H "Authorization: Bearer $PA_API_KEY"{
"contract": "pa-api/v1",
"usage": { "units": 1, "unit": "call", "billedCents": 5 },
"data": {
"a": "SWE.GEN.P5", "b": "SWE.GEN.P6", "space": "structural",
"edition": "2026-06.structural.1", "distance": 0.083, "band": "confident",
"explainer": "/jobframe/matching"
}
}Map your roster in one call
Keyed only ($0.02 / employee-row), up to 5,000 rows per call. Distinct titles resolve once and share the result across matching rows; every row carries the honest 3-state action.
curl -sS -X POST "$TOOLBOX_BASE_URL/api/v1/bulk-map" \
-H "Authorization: Bearer $PA_API_KEY" \
-H "content-type: application/json" \
-d '{
"rows": [
{ "ref": "emp-001", "title": "Senior Software Engineer" },
{ "ref": "emp-002", "title": "Sr. SWE II" }
]
}'{
"contract": "pa-api/v1",
"usage": { "units": 2, "unit": "row", "billedCents": 4 },
"data": {
"summary": { "total": 2, "autoAccept": 2, "needsReview": 0, "insufficientEvidence": 0 },
"rows": [
{ "ref": "emp-001", "title": "Senior Software Engineer", "action": "auto_accept",
"profileKey": "SWE.GEN.P5", "confidence": 0.94, "confidenceBand": "high", "alternatives": [] }
],
"explainer": "/jobframe/matching"
}
}CSV in? Transform the title column to rows: [{ ref, title }] first — the full quickstart (shell one-liner included) is in the API Adoption Kit linked above.
MCP variant (portfolio consumers)
The same capability is also reachable over MCP for AI-native consumers — a separate transport and auth system from the pa_… key above. MCP keys are operator-provisioned per consumer, not sold; there's no bridge from a Developer-plan purchase to MCP access today. Tool names: job-family-agent.resolve-title, job-family-agent.match, job-family-agent.coordinates.neighbors — there is no bulk-map tool over MCP; a roster means one call per row.
curl -sS -N -X POST "$TOOLBOX_BASE_URL/api/mcp" \
-H "Authorization: Bearer $TOOLBOX_MCP_KEY" \
-H "content-type: application/json" \
-H "accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "job-family-agent.resolve-title",
"arguments": { "title": "Senior Software Engineer" }
}
}'