{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://olfeed.org/schema/olf-1.0.json",
  "title": "Program feed (OLF 1.0 draft)",
  "description": "Structural rules for a university program feed. The online validator adds checks JSON Schema cannot express: source URLs on the owner domain for values the school publishes, verified dates not in the future, and at least one current price per program. Draft. The olf namespace is https://olfeed.org/ns#. Feeds must not include salary, career, job or occupation data (salaryUponCompletion, trainingSalary, occupationalCategory).",
  "type": "object",
  "required": [
    "@context",
    "@type",
    "olf:ownerDomain",
    "olf:feedVersion",
    "dataFeedElement"
  ],
  "properties": {
    "@context": {
      "description": "schema.org as the default vocabulary plus the olf prefix, or the shared context file at /vocab/context.jsonld.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^https://(olfeed\\.org|olf\\.mktgtech\\.workers\\.dev)/vocab/context\\.jsonld$"
        },
        {
          "type": "object",
          "required": [
            "@vocab",
            "olf"
          ],
          "properties": {
            "@vocab": {
              "type": "string",
              "pattern": "^https?://schema\\.org/?$"
            },
            "olf": {
              "const": "https://olfeed.org/ns#"
            }
          }
        },
        {
          "type": "array",
          "minItems": 1,
          "anyOf": [
            {
              "contains": {
                "type": "string",
                "pattern": "^https://(olfeed\\.org|olf\\.mktgtech\\.workers\\.dev)/vocab/context\\.jsonld$"
              }
            },
            {
              "allOf": [
                {
                  "contains": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^https?://schema\\.org/?$"
                      },
                      {
                        "type": "object",
                        "required": [
                          "@vocab"
                        ],
                        "properties": {
                          "@vocab": {
                            "type": "string",
                            "pattern": "^https?://schema\\.org/?$"
                          }
                        }
                      }
                    ]
                  }
                },
                {
                  "contains": {
                    "type": "object",
                    "required": [
                      "olf"
                    ],
                    "properties": {
                      "olf": {
                        "const": "https://olfeed.org/ns#"
                      }
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    },
    "@type": {
      "const": "olf:InstitutionProgramFeed"
    },
    "olf:ownerDomain": {
      "type": "string",
      "pattern": "^https://[a-z0-9.-]+$"
    },
    "olf:feedVersion": {
      "$ref": "#/$defs/date"
    },
    "dateModified": {
      "$ref": "#/$defs/date"
    },
    "olf:changeNotificationEndpoint": {
      "$ref": "#/$defs/httpsUrl"
    },
    "dataFeedElement": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/feedItem"
      }
    },
    "publisher": {
      "type": "object",
      "properties": {
        "contactPoint": {
          "type": "object",
          "properties": {
            "email": {
              "type": "string"
            },
            "url": {
              "type": "string",
              "pattern": "^https://"
            }
          }
        }
      }
    },
    "olf:includesFeed": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^https://"
        },
        {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^https://"
          }
        }
      ]
    }
  },
  "$defs": {
    "date": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "httpsUrl": {
      "type": "string",
      "pattern": "^https://"
    },
    "feedItem": {
      "type": "object",
      "required": [
        "@type",
        "dateModified",
        "item"
      ],
      "properties": {
        "@type": {
          "const": "DataFeedItem"
        },
        "dateModified": {
          "$ref": "#/$defs/date"
        },
        "item": {
          "$ref": "#/$defs/program"
        }
      }
    },
    "program": {
      "type": "object",
      "required": [
        "@type",
        "name",
        "olf:programStatus",
        "educationalProgramMode",
        "educationalCredentialAwarded",
        "offers"
      ],
      "properties": {
        "@type": {
          "const": "EducationalOccupationalProgram"
        },
        "@id": {
          "$ref": "#/$defs/httpsUrl"
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "url": {
          "$ref": "#/$defs/httpsUrl"
        },
        "olf:programStatus": {
          "enum": [
            "olf:AcceptingApplications",
            "olf:Launching",
            "olf:Paused",
            "olf:TeachOut",
            "olf:Discontinued"
          ]
        },
        "educationalProgramMode": {
          "enum": [
            "online",
            "onsite",
            "hybrid"
          ]
        },
        "educationalCredentialAwarded": {
          "type": "object",
          "required": [
            "educationalLevel"
          ],
          "properties": {
            "educationalLevel": {
              "enum": [
                "certificate",
                "associate",
                "bachelor",
                "master",
                "doctoral"
              ]
            }
          }
        },
        "numberOfCredits": {
          "type": "integer",
          "minimum": 1
        },
        "olf:transferCreditPolicy": {
          "type": "object",
          "properties": {
            "olf:maxTransferCredits": {
              "type": "integer",
              "minimum": 0
            },
            "olf:acceptedCreditSource": {
              "type": "array",
              "items": {
                "enum": [
                  "olf:PriorCollegeCredit",
                  "olf:MilitaryTraining",
                  "olf:CreditByExam",
                  "olf:PriorLearningAssessment",
                  "olf:Apprenticeship"
                ]
              }
            }
          }
        },
        "offers": {
          "type": "object",
          "required": [
            "priceSpecification"
          ],
          "properties": {
            "priceSpecification": {
              "type": "array",
              "minItems": 1,
              "items": {
                "oneOf": [
                  {
                    "$ref": "#/$defs/tuitionPrice"
                  },
                  {
                    "$ref": "#/$defs/discount"
                  }
                ]
              }
            }
          }
        },
        "olf:admissionTestPolicy": {
          "enum": [
            "olf:TestRequired",
            "olf:TestOptional",
            "olf:TestNotRequired",
            "olf:WaiverAvailable"
          ]
        },
        "startDate": {
          "$ref": "#/$defs/date"
        },
        "applicationDeadline": {
          "$ref": "#/$defs/date"
        },
        "timeToComplete": {
          "type": "string",
          "pattern": "^P(?=\\d)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?$"
        },
        "termDuration": {
          "type": "string",
          "pattern": "^P"
        },
        "termsPerYear": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "salaryUponCompletion": false,
        "trainingSalary": false,
        "occupationalCategory": false,
        "olf:concentration": false,
        "olf:focusArea": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1
              },
              "numberOfCredits": {
                "type": "integer",
                "minimum": 1
              },
              "olf:focusAreaType": {
                "enum": [
                  "olf:Concentration",
                  "olf:Specialization",
                  "olf:Track",
                  "olf:Emphasis",
                  "olf:Option"
                ]
              }
            }
          }
        },
        "olf:completionTime": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "olf:enrollmentIntensity",
              "olf:typicalDuration"
            ],
            "properties": {
              "olf:enrollmentIntensity": {
                "enum": [
                  "olf:FullTime",
                  "olf:PartTime",
                  "olf:Accelerated"
                ]
              },
              "olf:typicalDuration": {
                "type": "string",
                "pattern": "^P(?=\\d)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?$"
              },
              "olf:minimumDuration": {
                "type": "string",
                "pattern": "^P(?=\\d)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?$"
              },
              "olf:creditsPerTerm": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "olf:assumedTransferCredits": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "olf:classSchedule": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "olf:scheduleType"
            ],
            "properties": {
              "olf:scheduleType": {
                "enum": [
                  "olf:Daytime",
                  "olf:Evening",
                  "olf:Weekend",
                  "olf:SynchronousOnline",
                  "olf:AsynchronousOnline"
                ]
              },
              "byDay": {
                "oneOf": [
                  {
                    "type": "string",
                    "pattern": "^(https://schema\\.org/)?(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)$"
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^(https://schema\\.org/)?(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)$"
                    }
                  }
                ]
              },
              "startTime": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
              },
              "endTime": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
              },
              "scheduleTimezone": {
                "type": "string"
              },
              "repeatFrequency": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "audience": {
      "type": "object",
      "required": [
        "olf:eligibilityCategory"
      ],
      "properties": {
        "olf:eligibilityCategory": {
          "type": "array",
          "minItems": 1,
          "items": {
            "enum": [
              "olf:ActiveDutyMilitary",
              "olf:NationalGuard",
              "olf:Reservist",
              "olf:Veteran",
              "olf:MilitarySpouse",
              "olf:MilitaryDependent",
              "olf:MilitaryFamilyMember",
              "olf:FirstResponder",
              "olf:InStateResident",
              "olf:OutOfStateResident",
              "olf:InternationalStudent",
              "olf:EmployerPartner",
              "olf:TransferPartner"
            ]
          }
        }
      }
    },
    "provenance": {
      "type": "object",
      "required": [
        "olf:sourceUrl",
        "olf:verifiedDate"
      ],
      "properties": {
        "olf:sourceType": {
          "enum": [
            "olf:FederalReported",
            "olf:CommonDataSet",
            "olf:InstitutionPublished",
            "olf:InstitutionAttested",
            "olf:ThirdPartyAudited"
          ]
        },
        "olf:sourceUrl": {
          "$ref": "#/$defs/httpsUrl"
        },
        "olf:verifiedDate": {
          "$ref": "#/$defs/date"
        },
        "olf:contextNote": {
          "type": "string"
        }
      }
    },
    "tuitionPrice": {
      "type": "object",
      "required": [
        "@type",
        "price",
        "priceCurrency",
        "olf:tuitionBasis",
        "olf:provenance"
      ],
      "properties": {
        "@type": {
          "const": "olf:TuitionPriceSpecification"
        },
        "name": {
          "type": "string"
        },
        "price": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "priceCurrency": {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        "olf:tuitionBasis": {
          "enum": [
            "olf:PerCreditHour",
            "olf:PerCourse",
            "olf:PerTerm",
            "olf:PerAcademicYear",
            "olf:FlatRateProgram",
            "olf:SubscriptionTerm"
          ]
        },
        "priceComponentType": {
          "enum": [
            "olf:Tuition",
            "olf:TechnologyFee",
            "olf:CourseMaterialsFee",
            "olf:ApplicationFee",
            "olf:GraduationFee",
            "olf:LateRegistrationFee",
            "olf:TranscriptFee"
          ]
        },
        "validFrom": {
          "$ref": "#/$defs/date"
        },
        "validThrough": {
          "$ref": "#/$defs/date"
        },
        "olf:eligibleAudience": {
          "$ref": "#/$defs/audience"
        },
        "olf:provenance": {
          "$ref": "#/$defs/provenance"
        },
        "audience": {
          "$ref": "#/$defs/audience"
        }
      }
    },
    "discount": {
      "type": "object",
      "required": [
        "@type",
        "olf:provenance"
      ],
      "properties": {
        "@type": {
          "const": "olf:TuitionDiscount"
        },
        "name": {
          "type": "string"
        },
        "olf:discountPercent": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 100
        },
        "olf:discountAmount": {
          "type": "object",
          "required": [
            "value",
            "currency"
          ],
          "properties": {
            "@type": {
              "const": "MonetaryAmount"
            },
            "value": {
              "type": "number",
              "exclusiveMinimum": 0
            },
            "currency": {
              "type": "string",
              "pattern": "^[A-Z]{3}$"
            }
          }
        },
        "olf:eligibleAudience": {
          "$ref": "#/$defs/audience"
        },
        "olf:combinableWithOthers": {
          "type": "boolean"
        },
        "olf:provenance": {
          "$ref": "#/$defs/provenance"
        },
        "audience": {
          "$ref": "#/$defs/audience"
        }
      },
      "anyOf": [
        {
          "required": [
            "olf:discountPercent"
          ]
        },
        {
          "required": [
            "olf:discountAmount"
          ]
        }
      ]
    }
  }
}
