OpenAssignment · Draft specification 0.1.0

Specification

How a company publishes its consulting assignments as JSON on its own domain, and how consultants, agencies and matching services find and read them at the source.

Draft specification, version 0.1.0. This is an experimental first version, published to be tried out and criticised. Details may change before 1.0. Changes are listed in the changelog.

Overview

OpenAssignment defines two kinds of JSON documents and where to put them.

  • An entry file at a fixed address, /openassignment.json, which names the publisher and lists its assignments.
  • One assignment document per assignment, each at a URL of its own.

Both are ordinary files served over HTTPS. There is no API to implement, no registration and no central database.

The company that needs the work publishes the assignment on its own website. Everyone else reads it from there and links back to it. The information stays at the source, and the market connects around it.

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are used as described in RFC 2119.

Terms

  • Assignment: a defined piece of work that a company wants to buy from a consultant or a consulting company. It is a business-to-business engagement, not an employment.
  • Publisher: the organisation that publishes and maintains the assignment on its own domain. Normally the company that needs the work. The publisher is the source of the information.
  • Client: the organisation where the work is done. Usually the same as the publisher, and then it is not stated separately.
  • Facilitator: an agency or other intermediary that helps fill the assignment, for example by sourcing and qualifying consultants, managing procurement or handling the agreement. Optional. A facilitator is not the source of the information.
  • Consumer: any service that reads assignments in order to index, present or match them, such as a consulting company’s sales tool, an agency’s platform, a search service or an AI agent.
  • Source address: the permanent URL of the assignment’s JSON document on the publisher’s domain, stated in canonicalUrl.
  • Entry file: the JSON document that lists a publisher’s assignments.

Machine readable definitions

The schemas are written in JSON Schema, draft 2020-12. Where this text and a schema disagree, the schema is the mistake: please report it.

The entry file

A publisher MUST serve the entry file at the root of the domain it publishes for:

https://example.com/openassignment.json
/examples/manifest.jsonDownload /examples/manifest.json
{
  "$schema": "https://openassignment.io/schemas/v0.1/manifest.schema.json",
  "standard": "OpenAssignment",
  "schemaVersion": "0.1.0",
  "publisher": {
    "name": "Example Industries",
    "url": "https://openassignment.io/examples/"
  },
  "updatedAt": "2026-10-01T08:00:00Z",
  "assignments": [
    {
      "id": "urn:uuid:c4a7e2b1-3f58-4d9a-a6c0-7e1b5f2d8a43",
      "url": "https://openassignment.io/examples/assignment.json",
      "status": "open",
      "updatedAt": "2026-10-01T08:00:00Z",
      "htmlUrl": "https://openassignment.io/examples/#assignment"
    }
  ]
}
Fields of the entry file
FieldTypeStatusDescription
$schemastring (uri)OptionalURL of the schema this document follows.
standard"OpenAssignment"RequiredName of the standard.
schemaVersionstringRequiredVersion of OpenAssignment the entry file follows, for example "0.1.0".
publisherobjectRequiredThe organisation that publishes the assignments on this domain.
publisher.namestringRequiredName of the organisation.
publisher.urlstring (uri)OptionalThe organisation's website.
updatedAtstring (date-time)RequiredWhen the entry file or any listed assignment last changed.
assignmentsarray of objectRequiredOne entry per published assignment. An empty list is valid.
assignments[].idstringRequiredThe assignment's stable identifier, identical to id in the assignment.
assignments[].urlstring (uri)RequiredThe assignment's source address, identical to canonicalUrl in the assignment.
assignments[].status"open" | "paused" | "filled" | "closed"RequiredCurrent status, identical to status in the assignment. Lets clients notice a closed assignment without fetching it.
assignments[].updatedAtstring (date-time)RequiredWhen the assignment last changed. Lets clients skip assignments they already have.
assignments[].htmlUrlstring (uri)OptionalURL of the human readable page.

Rules for the entry file:

  • Every url MUST be absolute, use HTTPS and equal canonicalUrl in the assignment it points to.
  • Every id and status MUST equal the values in the assignment it points to.
  • updatedAt MUST change whenever an assignment is added, changed or removed.
  • An assignment that is no longer open SHOULD stay in the list with its new status for at least 30 days, so that consumers learn that it has closed. After that it MAY be removed.

The assignment

Fields of an assignment
FieldTypeStatusDescription
$schemastring (uri)OptionalURL of the schema this document follows.
schemaVersionstringRequiredVersion of OpenAssignment the document follows, for example "0.1.0".
idstringRequiredStable identifier of the assignment, unique within the publisher. Must never change or be reused, even if the title or the file name changes. A UUID URN is recommended.
canonicalUrlstring (uri)RequiredThe source address: the permanent URL of this JSON document on the publisher's own domain. Every service that presents the assignment links back to it.
titlestringRequiredTitle of the assignment, normally the role that is needed.
descriptionstringRequiredWhat the work is: background, tasks and expected outcome. Plain text. Line breaks separate paragraphs.
publisherobjectRequiredThe organisation that publishes and maintains the assignment on its own domain. Normally the company that needs the work. The publisher is the source of the information.
publisher.namestringRequiredName of the organisation.
publisher.urlstring (uri)OptionalThe organisation's website.
clientobjectOptionalThe organisation where the work is done, when that is not the publisher. Leave out when the publisher is the client.
client.namestringRequired in parentName of the organisation.
client.urlstring (uri)OptionalThe organisation's website.
facilitatorobjectOptionalAn agency or other intermediary that helps fill the assignment, for example by sourcing, qualifying or contracting consultants. Optional. A facilitator is not the source of the information: the publisher is.
facilitator.namestringRequired in parentName of the facilitating organisation.
facilitator.urlstring (uri)OptionalThe facilitator's website.
facilitator.rolestringOptionalWhat the facilitator does for this assignment, in a sentence.
requiredSkillsarray of objectOptionalSkills a consultant must have.
requiredSkills[].namestringRequired in parentName of the skill.
requiredSkills[].levelstringOptionalExpected level, for example "Senior".
requiredSkills[].keywordsarray of stringOptionalSpecific technologies, methods or tools within the skill.
preferredSkillsarray of objectOptionalSkills that count in a consultant's favour but are not mandatory.
preferredSkills[].namestringRequired in parentName of the skill.
preferredSkills[].levelstringOptionalExpected level, for example "Senior".
preferredSkills[].keywordsarray of stringOptionalSpecific technologies, methods or tools within the skill.
locationobjectOptionalWhere on-site work takes place.
location.citystringOptionalCity or town.
location.regionstringOptionalRegion, county or state.
location.countryCodestringOptionalISO 3166-1 alpha-2 country code, for example "SE".
remote"onsite" | "hybrid" | "remote"OptionalWay of working. onsite: at the client. hybrid: a mix of on-site and remote. remote: fully remote.
engagementType"full-time" | "part-time" | "project"OptionalForm of the assignment. full-time and part-time are engagements paid by time. project is a delivery with a defined scope.
workloadobjectOptionalHow much work the assignment is.
workload.percentintegerOptionalShare of full time, in percent.
workload.hoursPerWeeknumberOptionalExpected hours per week.
workload.descriptionstringOptionalFree text for anything the numbers do not capture.
startDatestring (date)OptionalExpected first day of the assignment.
endDatestring (date)OptionalExpected last day, if known.
status"open" | "paused" | "filled" | "closed"Requiredopen: accepting interest. paused: temporarily not accepting interest. filled: a consultant has been appointed. closed: withdrawn or ended without being filled.
publishedAtstring (date-time)RequiredWhen the assignment was first published.
updatedAtstring (date-time)RequiredWhen the assignment last changed, including changes of status.
expiresAtstring (date-time)OptionalAfter this moment the assignment must no longer be presented as open, whatever status says.
applicationUrlstring (uri)OptionalWhere to register interest: a web page or a mailto: address, at the publisher or at the facilitator.
htmlUrlstring (uri)OptionalURL of the human readable page at the publisher showing the same assignment.

Nine fields are required. An assignment with only those looks like this:

/examples/assignment.minimal.jsonDownload /examples/assignment.minimal.json
{
  "schemaVersion": "0.1.0",
  "id": "urn:uuid:9d3f6a70-52c1-4b8e-8f2a-0c6e4b1d7a95",
  "canonicalUrl": "https://openassignment.io/examples/assignment.minimal.json",
  "title": "Data Engineer",
  "description": "Six months of work on a data platform migration.",
  "publisher": {
    "name": "Example Industries"
  },
  "status": "open",
  "publishedAt": "2026-10-01T08:00:00Z",
  "updatedAt": "2026-10-01T08:00:00Z"
}

The source and the roles around it

An assignment has one original, and it lives with the company that published it. Everything else in this specification follows from that.

The publisher is the source. The publisher writes the assignment, serves it from its own domain and keeps it current. Only the publisher changes it.

The source address is permanent. canonicalUrl is the address of the original. It MUST be an HTTPS URL on a domain the publisher controls, MUST be the address the document is actually served from, and SHOULD NOT change during the lifetime of the assignment.

The client is usually the publisher. When the company that needs the work publishes the assignment itself, client is left out. When one organisation publishes for another, for example a parent company for a subsidiary, publisher names the one that publishes and client names the one where the work is done.

A facilitator helps, but is not the source. Many companies work with an agency that sources and qualifies consultants, manages procurement or handles the agreement. The publisher MAY name that agency in facilitator and MAY point applicationUrl to it. This does not move the original: the assignment is still published and maintained by the publisher, at the publisher’s address.

{
  "publisher": { "name": "Example Industries", "url": "https://example.com/" },
  "facilitator": {
    "name": "Example Sourcing",
    "url": "https://sourcing.example/",
    "role": "Qualifies consultants and manages the agreement on behalf of Example Industries."
  }
}

Consumers build on the source. Agencies, platforms and other services are free to index assignments, present them, match them against consultants and build services around them. They do so from the original, link back to it and follow its updates. The rules are in Reading assignments.

Identity

An assignment is identified by id, not by its URL and not by its title.

  • The id MUST be unique within the publisher and MUST NOT change during the lifetime of the assignment.
  • The id MUST NOT be reused for another assignment.
  • A random UUID written as a URN, such as urn:uuid:c4a7e2b1-3f58-4d9a-a6c0-7e1b5f2d8a43, is recommended.

When the same assignment is presented by several services, the source address and the id let everyone recognise it as one assignment with one original.

Status and expiry

An assignment that has closed must not go on being presented as open. This is the part of the standard that matters most.

Status Meaning
open The publisher accepts expressions of interest.
paused Temporarily not accepting interest. May open again.
filled A consultant has been appointed.
closed Withdrawn, or ended without being filled.

Publishers:

  • MUST change status as soon as an assignment is no longer open.
  • MUST change updatedAt, in both the assignment and the entry file, whenever the status changes.
  • SHOULD set expiresAt, so that an assignment closes by itself if nobody remembers to update it.

Consumers:

  • MUST NOT present an assignment as open unless status is open.
  • MUST NOT present an assignment as open after expiresAt has passed.
  • MUST stop presenting an assignment as open if its file can no longer be fetched or it has disappeared from the entry file.
  • SHOULD read the entry file again at least once a day for as long as they show any of its assignments.

Assignments are not jobs

OpenAssignment describes consulting engagements, not employment. That is why the format has fields a job advert lacks, and lacks fields a job advert has.

  • publisher, client and facilitator are separate roles, because the company that needs the work, the place where it is done and the agency that helps fill it can be three different organisations.
  • engagementType and workload describe a purchase of time or of a delivery. There is no salary, no benefits and no employment form.
  • startDate and endDate describe a limited period.

A consumer MUST NOT present an assignment as an offer of employment.

Relation to existing standards

The format was designed after reviewing Schema.org JobPosting and the JSON Resume project’s job description schema. Both are built around employment and have no way to express the status of an assignment or to name a facilitator alongside the company that needs the work, so OpenAssignment defines its own schema. Field names and structures are kept close to them where the meaning is the same: location and the skill objects use the JSON Resume shapes, which is also what OpenConsultant uses.

Publishers who also want their page understood by search engines can derive JobPosting markup from an assignment:

OpenAssignment Schema.org JobPosting
title title
description description
publisher hiringOrganization
location jobLocation
remote jobLocationType
engagementType employmentType, with the value CONTRACTOR
requiredSkills skills
startDate jobStartDate
publishedAt datePosted
expiresAt validThrough
id identifier

Human readable pages

The same assignment SHOULD also exist as an ordinary web page. Link the two together:

  • In the assignment, set htmlUrl to the page.
  • On the page, point to the JSON with a link element:
<link rel="alternate" type="application/json" href="https://example.com/assignments/frontend-developer.json" />

The page and the JSON SHOULD be generated from the same source, so they cannot drift apart.

Serving the files

  • Files MUST be served over HTTPS.
  • Files MUST be retrievable with a plain GET request, without authentication, cookies or JavaScript.
  • The Content-Type MUST be application/json.
  • Files SHOULD allow cross-origin reads by sending Access-Control-Allow-Origin: *.
  • Files MUST be encoded as UTF-8.

Reading assignments

A consumer finds and reads a publisher’s assignments in three steps.

  1. Fetch https://<domain>/openassignment.json.
  2. Check that standard is OpenAssignment and that it understands the schemaVersion.
  3. Fetch each url in assignments. Use status and updatedAt to skip assignments that are closed or have not changed.

Consumers:

  • MUST ignore fields they do not recognise.
  • MUST follow the rules under Status and expiry.
  • MUST keep canonicalUrl with every copy and, wherever they present the assignment, link back to the original: to htmlUrl when there is one, otherwise to canonicalUrl.
  • MUST name the publisher as the source, and MUST NOT present themselves or a facilitator as the origin of the assignment.
  • MUST replace their copy when the original changes, and SHOULD NOT alter the content they present.
  • SHOULD send people who want to respond to applicationUrl.
  • SHOULD identify themselves with a descriptive User-Agent.

Consumers MAY add their own services around an assignment, such as matching, qualification or advice, as long as it stays clear what comes from the publisher and what the consumer has added.

Discovery in this version relies only on the fixed address. Later versions may add other mechanisms, such as .well-known or HTML metadata, without removing this one.

Extending the format

Unknown fields are allowed everywhere. Publishers MAY add their own. To avoid clashes with future versions of the standard, custom fields SHOULD start with x-, for example x-securityClearance.

Versioning

  • Versions follow Semantic Versioning. This is 0.1.0.
  • schemaVersion states which version a document follows.
  • Each published minor version of the schemas has a permanent URL, for example /schemas/v0.1/schema.json. Published schema files are not changed in incompatible ways.
  • Additions that old consumers can safely ignore are made within a version line. Breaking changes get a new version and a new schema URL.

Privacy and responsibility

Everything published according to this standard is public. The publisher decides what to publish and is responsible for it. That is the point of publishing at the source: the company that owns the information stays in control of it.

Client and facilitator. If you publish for another organisation, name it as client only when it has agreed to that. Name a facilitator only when the agency has agreed to be named. Do not publish internal project names, budgets, rates, procurement details or anything covered by a confidentiality agreement.

Personal data. An assignment should not need any. Use a functional address or a web form in applicationUrl, not a named person’s private contact details. If you do publish personal data, such as a contact person’s name, the GDPR applies within the EU and EEA and you need a legal basis and must have informed the person.

What not to publish. Never put secrets, API keys or internal identifiers from business systems in an assignment. Do not describe security arrangements or systems in more detail than a public advert would.

Updating and unpublishing. Change status when an assignment closes and keep it listed for a while, as described above. To withdraw an assignment completely, remove it from the entry file and stop serving the file. A removed file SHOULD answer with HTTP 404 or 410.

Reuse. Consumers MAY index, present and redistribute assignments. They are responsible for keeping their copies current, MUST honour status changes and removals, and MUST link back to the original.