{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://humanjson.org/schema/human.schema.json",
  "title": "human.json profile (human.json)",
  "description": "Who a person is, what they're open to (jobs, freelance, advising, ...), what they're not open to, and how agents may approach them. A public file: put in only what you'd tell anyone. Published at /.well-known/human.json or anywhere linked from the person's pages.",
  "type": "object",
  "required": [
    "spec",
    "name",
    "headline",
    "location",
    "agent_policy"
  ],
  "properties": {
    "spec": {
      "type": "string",
      "pattern": "^(human\\.json|hellohuman|approach|open-hire)/0\\.[0-9]+$",
      "description": "Version of this spec, e.g. human.json/0.4 (open-hire/0.x files are still accepted)"
    },
    "handle": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120
    },
    "pronouns": {
      "type": "string",
      "maxLength": 40
    },
    "headline": {
      "type": "string",
      "minLength": 1,
      "maxLength": 300
    },
    "photo": {
      "type": "string",
      "maxLength": 500,
      "pattern": "^https://",
      "description": "Optional. An https URL to a square-ish photo of the person (for example their GitHub avatar). Pages show initials without it."
    },
    "location": {
      "type": "object",
      "required": [
        "city",
        "utc_offset"
      ],
      "properties": {
        "city": {
          "type": "string",
          "minLength": 1
        },
        "country": {
          "type": "string",
          "description": "ISO 3166-1 alpha-2, e.g. DE"
        },
        "utc_offset": {
          "type": "number",
          "minimum": -12,
          "maximum": 14
        }
      }
    },
    "status": {
      "enum": [
        "looking",
        "open",
        "not-looking"
      ]
    },
    "updated": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "summary": {
      "type": "string",
      "maxLength": 2000
    },
    "links": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/link"
      }
    },
    "languages": {
      "type": "array",
      "maxItems": 12,
      "description": "Languages the person works in, most preferred first. Agents write in the first one they can.",
      "items": {
        "type": "object",
        "required": [
          "tag"
        ],
        "additionalProperties": false,
        "properties": {
          "tag": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "description": "A BCP 47 language tag, e.g. en, de, pt-BR."
          },
          "level": {
            "enum": [
              "native",
              "fluent",
              "working",
              "basic"
            ]
          }
        }
      }
    },
    "availability": {
      "type": "object",
      "additionalProperties": false,
      "description": "When and how to get time with the person.",
      "properties": {
        "booking_url": {
          "type": "string",
          "pattern": "^https://",
          "maxLength": 500,
          "description": "A scheduling link. Agents offer it only after a request passes the person's rules."
        },
        "away_until": {
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "Away until this date: agents expect no reply and don't follow up before it."
        },
        "note": {
          "type": "string",
          "maxLength": 200
        }
      }
    },
    "identities": {
      "type": "array",
      "maxItems": 10,
      "description": "The person's other accounts and sites. An agent trusts one only if that page links back to this file or the person's human.json page (rel=\"me\").",
      "items": {
        "type": "object",
        "required": [
          "url"
        ],
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "pattern": "^https://",
            "maxLength": 300
          },
          "label": {
            "type": "string",
            "maxLength": 60
          }
        }
      }
    },
    "open_to": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/intent"
      },
      "description": "Each thing the person is open to, with its own conditions. Anything not listed is a no."
    },
    "not_open_to": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Types agents should decline without contacting the person, e.g. sales, recruiting_agency."
    },
    "looking_for": {
      "type": "object",
      "description": "Deprecated in v0.3: the same as one open_to entry of type \"job\". Still accepted.",
      "properties": {
        "roles": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "seniority": {
          "enum": [
            "junior",
            "mid",
            "senior",
            "staff",
            "principal",
            "lead",
            "head"
          ]
        },
        "employment": {
          "type": "array",
          "items": {
            "enum": [
              "full-time",
              "part-time",
              "contract",
              "freelance"
            ]
          }
        },
        "work_mode": {
          "type": "array",
          "minItems": 1,
          "items": {
            "enum": [
              "remote",
              "hybrid",
              "onsite"
            ]
          }
        },
        "locations": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Cities for hybrid or onsite work"
        },
        "relocate": {
          "type": "boolean"
        },
        "max_tz_diff_hours": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 24
        },
        "work_auth": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Where they can already work: EU, UK, US, CA, ..."
        },
        "needs_sponsorship": {
          "type": "boolean"
        },
        "comp": {
          "type": "object",
          "properties": {
            "currency": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Z]{3}$"
            },
            "base_min": {
              "type": [
                "number",
                "null"
              ],
              "minimum": 0
            },
            "target": {
              "type": [
                "number",
                "null"
              ],
              "minimum": 0
            },
            "disclose": {
              "enum": [
                "public",
                "on-match",
                "human"
              ],
              "description": "public: the number is in the file (it is public either way); human: the number is left out and discussed in person. on-match is from v0.2 and is treated as public."
            }
          }
        },
        "start": {
          "type": "string",
          "pattern": "^(\\d{4}-\\d{2}-\\d{2})?$"
        },
        "stages": {
          "type": "array",
          "items": {
            "enum": [
              "seed",
              "series-a",
              "series-b",
              "growth",
              "public",
              "nonprofit"
            ]
          }
        },
        "domains_avoid": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "domains_prefer": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "max_on_call": {
          "enum": [
            "none",
            "light",
            "heavy"
          ]
        },
        "deal_breakers": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "nice_to_haves": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "work_mode"
      ]
    },
    "skills": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "level"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Prefer names from vocabulary.json so agents match them exactly"
          },
          "level": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "years": {
            "type": "number",
            "minimum": 0
          },
          "evidence": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "ids of projects that show this skill"
          }
        }
      }
    },
    "projects": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "title"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9-]*$"
          },
          "title": {
            "type": "string",
            "minLength": 1
          },
          "year": {
            "type": "integer",
            "minimum": 1950,
            "maximum": 2100
          },
          "role": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "outcome": {
            "type": "string",
            "description": "What changed because of it, ideally measurable"
          },
          "stack": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "link": {
            "type": "string"
          },
          "source": {
            "enum": [
              "github",
              "linkedin",
              "json-resume",
              "self"
            ],
            "description": "github means the link is a public repository anyone can check"
          }
        }
      }
    },
    "experience": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "org"
        ],
        "properties": {
          "org": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          }
        }
      }
    },
    "faq": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "q",
          "a"
        ],
        "properties": {
          "q": {
            "type": "string",
            "minLength": 1
          },
          "a": {
            "type": "string",
            "minLength": 1
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    },
    "references": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "quote"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "relation": {
            "type": "string"
          },
          "quote": {
            "type": "string"
          },
          "contact": {
            "type": "string"
          }
        }
      }
    },
    "agent_policy": {
      "type": "object",
      "required": [
        "contact"
      ],
      "properties": {
        "intro_requires": {
          "type": "array",
          "items": {
            "enum": [
              "written_jd",
              "published_comp",
              "named_hiring_manager"
            ]
          }
        },
        "auto_decline": {
          "type": "boolean",
          "description": "Agents may decline on the person's behalf when a hard condition fails"
        },
        "escalate": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Topics agents must leave to the person"
        },
        "contact": {
          "type": "object",
          "required": [
            "method"
          ],
          "properties": {
            "method": {
              "enum": [
                "email",
                "url"
              ]
            },
            "address": {
              "type": "string"
            },
            "url": {
              "type": "string"
            },
            "subject_prefix": {
              "type": "string"
            }
          }
        },
        "response_time": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        },
        "feedback": {
          "type": "object",
          "required": [
            "url"
          ],
          "description": "Where agents send a short structured note after deciding: approached, asked or declined, and why",
          "properties": {
            "url": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      }
    },
    "sources": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "ref": {
            "type": "string"
          },
          "imported": {
            "type": "string"
          }
        }
      }
    }
  },
  "definitions": {
    "link": {
      "type": "object",
      "required": [
        "url"
      ],
      "properties": {
        "label": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "pattern": "^https?://"
        }
      }
    },
    "intent": {
      "type": "object",
      "required": [
        "type"
      ],
      "properties": {
        "roles": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "seniority": {
          "enum": [
            "junior",
            "mid",
            "senior",
            "staff",
            "principal",
            "lead",
            "head"
          ]
        },
        "employment": {
          "type": "array",
          "items": {
            "enum": [
              "full-time",
              "part-time",
              "contract",
              "freelance"
            ]
          }
        },
        "work_mode": {
          "type": "array",
          "minItems": 1,
          "items": {
            "enum": [
              "remote",
              "hybrid",
              "onsite"
            ]
          }
        },
        "locations": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Cities for hybrid or onsite work"
        },
        "relocate": {
          "type": "boolean"
        },
        "max_tz_diff_hours": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 24
        },
        "work_auth": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Where they can already work: EU, UK, US, CA, ..."
        },
        "needs_sponsorship": {
          "type": "boolean"
        },
        "comp": {
          "description": "job: {currency, base_min, target, disclose}; advising: list of accepted forms",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "currency": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "pattern": "^[A-Z]{3}$"
                },
                "base_min": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0
                },
                "target": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0
                },
                "disclose": {
                  "enum": [
                    "public",
                    "on-match",
                    "human"
                  ],
                  "description": "public: the number is in the file (it is public either way); human: the number is left out and discussed in person. on-match is from v0.2 and is treated as public."
                }
              }
            },
            {
              "type": "array",
              "items": {
                "enum": [
                  "paid",
                  "equity",
                  "none"
                ]
              }
            }
          ]
        },
        "start": {
          "type": "string",
          "pattern": "^(\\d{4}-\\d{2}-\\d{2})?$"
        },
        "stages": {
          "type": "array",
          "items": {
            "enum": [
              "seed",
              "series-a",
              "series-b",
              "growth",
              "public",
              "nonprofit"
            ]
          }
        },
        "domains_avoid": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "domains_prefer": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "max_on_call": {
          "enum": [
            "none",
            "light",
            "heavy"
          ]
        },
        "deal_breakers": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "nice_to_haves": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "type": {
          "enum": [
            "job",
            "freelance",
            "advising",
            "cofounder",
            "investing",
            "speaking",
            "intro",
            "sales",
            "recruiting_agency"
          ],
          "description": "What this entry is about. Requests carry the same type; agents match a request to the entry of its type."
        },
        "status": {
          "enum": [
            "looking",
            "open",
            "not-looking"
          ]
        },
        "rate": {
          "type": "object",
          "description": "freelance: day rate",
          "properties": {
            "currency": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Z]{3}$"
            },
            "day_min": {
              "type": [
                "number",
                "null"
              ],
              "minimum": 0
            },
            "disclose": {
              "enum": [
                "public",
                "on-match",
                "human"
              ],
              "description": "public: the number is in the file (it is public either way); human: the number is left out and discussed in person. on-match is from v0.2 and is treated as public."
            }
          }
        },
        "max_days_per_week": {
          "type": "number",
          "minimum": 0,
          "maximum": 7
        },
        "min_weeks": {
          "type": "number",
          "minimum": 0
        },
        "max_weeks": {
          "type": "number",
          "minimum": 0
        },
        "max_hours_per_month": {
          "type": "number",
          "minimum": 0,
          "description": "advising"
        },
        "intro_requires": {
          "type": "array",
          "items": {
            "enum": [
              "written_jd",
              "published_comp",
              "named_hiring_manager"
            ]
          }
        },
        "notes": {
          "type": "string"
        },
        "topics": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "intro, speaking, advising: what they want to talk about. Requests on other topics are declined."
        }
      }
    }
  },
  "anyOf": [
    {
      "required": [
        "open_to"
      ]
    },
    {
      "required": [
        "looking_for"
      ]
    }
  ]
}
