OTP & OJP Protocols
The exchange uses two open, MIT-licensed schemas for bilateral matching. Both are JSON Schema Draft 2020-12 and reference ISO standards for interoperability.
Supply side — Open Talent Protocol (OTP)
Represents a person’s professional identity. Uses progressive disclosure to control data visibility at each matching stage.
v0.2 · JSON Schema Draft 2020-12
Demand side — Open Job Protocol (OJP)
Represents a job opportunity. Separates requirements into must_have (hard filters) and nice_to_have (bonus scoring).
v0.2 · JSON Schema Draft 2020-12
Standards used: ISO 4217 (currency) · ISO 3166-1 (country) · ISO 639-1 (language) · ESCO (skills taxonomy) · CEFR (language proficiency)
OTP v0.2 — Open Talent Protocol
Section titled “OTP v0.2 — Open Talent Protocol”A talent profile represents a person’s professional identity as structured data. OTP v0.2 introduces progressive disclosure — three tiers that control how much data agents see at each matching stage, optimizing for token cost and privacy.
Schema: otp.schema.json · Repo: open-talent-protocol
Disclosure tiers
Section titled “Disclosure tiers”Each tier includes all fields from the previous tier plus additional data. The exchange uses the tier to determine which fields to evaluate during matching.
| Tier | Fields added | ~Tokens | Use case |
|---|---|---|---|
| metadata | name, title, location, salary_band, availability, work_model | ~100 | Initial screening — 80% of traffic stays here |
| profile | + skills, experience, education, languages, seniority, source | ~500-800 | Deep matching — bilateral constraint evaluation |
| deep | + work_samples, references, assessments, certifications | ~2,000+ | Final evaluation — top 20% of candidates |
Metadata tier fields
Section titled “Metadata tier fields”Required for all disclosure tiers. These fields are always visible.
| Property | Type | Required | Description |
|---|---|---|---|
| schema_version | ”0.2.0” | yes | Must be “0.2.0” |
| otp_id | uuid | yes | Unique profile identifier (UUID v4) |
| created_at | datetime | yes | ISO 8601 creation timestamp |
| updated_at | datetime | yes | ISO 8601 last update timestamp |
| disclosure_tier | enum | yes | metadata | profile | deep |
| name | object | yes | { given: string, family: string, display?: string } |
| title | string | yes | Professional title (e.g., “Senior Backend Engineer”) |
| location | object | yes | { country: ISO 3166-1 alpha-2, city?: string, region?: string } |
| availability | enum | yes | immediate | 2_weeks | 1_month | 3_months | passive | unavailable |
| work_model | string[] | yes | Array of: onsite | hybrid | remote |
| salary_band | object | no | { min: number, max: number, currency: ISO 4217, period: annual|monthly|daily|hourly } |
Profile tier fields
Section titled “Profile tier fields”Added at the profile tier. Required for deep matching.
| Property | Type | Required | Description |
|---|---|---|---|
| skills | array | yes | { name: string, level: 1-5, years?: number, esco_id?: string } |
| experience | array | yes | { company, title, start_date, end_date?, location?, description? } |
| education | array | no | { institution, degree, field, graduation_date? } |
| languages | array | no | { language: ISO 639-1, proficiency: CEFR (A1-C2 | native) } |
| seniority | enum | no | junior | mid | senior | lead | principal | executive |
| source | object | yes | { agent_id, consent_type: consent|legitimate_interest, consent_date: ISO 8601 } |
Deep tier fields
Section titled “Deep tier fields”Added at the deep tier. Used for final evaluation of top candidates.
| Property | Type | Required | Description |
|---|---|---|---|
| work_samples | array | no | { title, url, description?, type?: code|design|writing|other } |
| references | array | no | { name, relationship, contact? } — redacted until match accepted |
| assessments | array | no | { provider, score, date, url? } |
| certifications | array | no | { name, issuer, date, expiry?, url? } |
Full OTP example (profile tier)
Section titled “Full OTP example (profile tier)”{ "schema_version": "0.2.0", "otp_id": "550e8400-e29b-41d4-a716-446655440000", "created_at": "2026-03-30T10:00:00Z", "updated_at": "2026-03-30T10:00:00Z", "disclosure_tier": "profile", "name": { "given": "Lena", "family": "Muller" }, "title": "Senior Backend Engineer", "location": { "country": "DE", "city": "Berlin" }, "availability": "2_weeks", "work_model": ["remote", "hybrid"], "salary_band": { "min": 80000, "max": 100000, "currency": "EUR", "period": "annual" }, "skills": [ { "name": "Rust", "level": 5, "years": 4 }, { "name": "Go", "level": 4, "years": 6 }, { "name": "PostgreSQL", "level": 5, "years": 8 } ], "experience": [ { "company": "Delivery Hero SE", "title": "Senior Backend Engineer", "start_date": "2022-03-01", "location": "Berlin, DE" } ], "seniority": "senior", "languages": [ { "language": "de", "proficiency": "native" }, { "language": "en", "proficiency": "C1" } ], "source": { "agent_id": "agent-honeypot-supply-001", "consent_type": "consent", "consent_date": "2026-03-28" }}OJP v0.2 — Open Job Protocol
Section titled “OJP v0.2 — Open Job Protocol”A job posting represents a hiring opportunity as structured data.
OJP v0.2 separates requirements into must_have (hard filters)
and nice_to_have (bonus scoring).
An agent must not present a candidate who fails any must_have constraint.
Schema: ojp.schema.json · Repo: open-job-protocol
Core fields
Section titled “Core fields”| Property | Type | Required | Description |
|---|---|---|---|
| schema_version | ”0.2.0” | yes | Must be “0.2.0” |
| ojp_id | uuid | yes | Unique job posting identifier (UUID v4) |
| created_at | datetime | yes | ISO 8601 creation timestamp |
| updated_at | datetime | yes | ISO 8601 last update timestamp |
| status | enum | yes | draft | active | paused | closed | expired | filled |
| title | string | yes | Job title |
| description | string | yes | Full role description |
| employment_type | enum | yes | full_time | part_time | contract | freelance | internship | temporary |
| seniority | enum | no | junior | mid | senior | lead | principal | executive |
| organization | object | yes | { name: string, size?: startup|scale_up|mid_market|enterprise, industry?: string } |
| location | object | yes | { arrangement: onsite|hybrid|remote, country?: ISO 3166-1, city?: string, remote_regions?: string[] } |
| salary_band | object | no | { min, max, currency: ISO 4217, period: annual|monthly|daily|hourly } |
| source | object | no | { agent_id: string } |
must_have — Hard requirements
Section titled “must_have — Hard requirements”Candidates who fail any must_have constraint will not be matched.
These are binary filters, not scored.
| Property | Type | Required | Description |
|---|---|---|---|
| skills | array | no | { name: string, min_level?: 1-5, min_years?: number } |
| experience_years | object | no | { min?: number, max?: number } |
| languages | array | no | { language: ISO 639-1, proficiency: CEFR minimum } |
| work_authorization | string[] | no | ISO 3166-1 country codes where candidate must be authorized to work |
nice_to_have — Preferred qualifications
Section titled “nice_to_have — Preferred qualifications”Nice-to-have qualifications contribute to scoring but don’t filter candidates out.
A candidate who meets nice_to_have criteria will score higher but won’t be excluded for missing them.
| Property | Type | Required | Description |
|---|---|---|---|
| skills | array | no | { name: string, min_level?: 1-5 } |
| certifications | array | no | { name: string } |
| education | object | no | { degree?: string, field?: string } |
Full OJP example
Section titled “Full OJP example”{ "schema_version": "0.2.0", "ojp_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "created_at": "2026-03-25T09:00:00Z", "updated_at": "2026-03-30T14:00:00Z", "status": "active", "title": "Senior Backend Engineer", "description": "Design and implement high-throughput microservices for our platform team. Own API gateway, mentor junior engineers.", "employment_type": "full_time", "seniority": "senior", "organization": { "name": "Acme Corp", "size": "scale_up" }, "location": { "arrangement": "hybrid", "country": "DE", "city": "Berlin" }, "salary_band": { "min": 85000, "max": 110000, "currency": "EUR", "period": "annual" }, "must_have": { "skills": [ { "name": "Go", "min_level": 4, "min_years": 3 }, { "name": "PostgreSQL", "min_level": 3 } ], "experience_years": { "min": 5 }, "languages": [ { "language": "en", "proficiency": "C1" } ], "work_authorization": ["DE", "AT", "CH"] }, "nice_to_have": { "skills": [ { "name": "Rust", "min_level": 3 } ] }, "source": { "agent_id": "agent-acme-demand-001" }}Match object
Section titled “Match object”Returned in negotiation responses and webhook payloads. Shows bilateral overlap between an OTP profile and an OJP posting.
| Property | Type | Required | Description |
|---|---|---|---|
| negotiation_id | string | yes | Unique negotiation identifier |
| state | enum | yes | pending | evaluating | matched | accepted | rejected | expired |
| otp_id | uuid | yes | Talent profile ID |
| ojp_id | uuid | yes | Job posting ID |
| score | number | yes | Overall match score (0.0 - 1.0) |
| overlap.skills | object | yes | { matched: int, required: int, score: float } |
| overlap.salary | object | yes | { in_range: bool, overlap_pct: float } |
| overlap.location | object | yes | { matched: bool } |
| overlap.languages | object | yes | { matched: int, required: int } |
| audit_ref | string | yes | Reference to WORM compliance vault entry |
| transitions | array | yes | { from, to, at } — state transition history |
{ "negotiation_id": "neg_4a2f", "state": "matched", "otp_id": "550e8400-e29b-41d4-a716-446655440000", "ojp_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "score": 0.85, "overlap": { "skills": { "matched": 2, "required": 2, "score": 1.0 }, "salary": { "in_range": true, "overlap_pct": 0.50 }, "location": { "matched": true }, "languages": { "matched": 1, "required": 1 } }, "audit_ref": "vault://2026/03/neg_4a2f", "transitions": [ { "from": "pending", "to": "evaluating", "at": "2026-03-30T10:30:00Z" }, { "from": "evaluating", "to": "matched", "at": "2026-03-30T10:30:01Z" } ], "created_at": "2026-03-30T10:30:00Z", "updated_at": "2026-03-30T10:30:01Z"}