University of Macau · API Governance Rules

University of Macau API Rules

Spectral linting rules defining API design standards and conventions for University of Macau.

15 Rules error 6 warn 9
View Rules File View on GitHub

Rule Categories

api documents info operation parameter path query read success

Rules

warn
read-only-surface
Every operation on this platform is a GET. A non-GET operation would be a change in kind for an open-data publication surface and should be deliberate.
$.paths[*]
error
operation-has-tag
Every operation must carry at least one tag naming its data set.
$.paths[*][get]
error
operation-has-operation-id
Every operation must declare an operationId.
$.paths[*][get]
warn
operation-id-snake-case
operationId follows this API's snake_case convention.
$.paths[*][get].operationId
warn
operation-has-description
Every operation must describe what the data set contains.
$.paths[*][get]
warn
path-segment-snake-case
Path segments use lower snake_case (service/facilities/car_park_availability/all).
$.paths
warn
query-param-snake-case
Query parameter names use lower snake_case (date_from, course_code, sort_by). Path template parameters inherited from the gateway are camelCase and are deliberately out of scope.
$.paths[*][get].parameters[?(@.in == 'query')].name
warn
parameter-has-description
Every declared parameter should say what it filters or controls.
$.paths[*][get].parameters[?(@.name)]
error
documents-401
Every operation is subscription-key protected and must document the 401 the gateway returns without one.
$.paths[*][get].responses
warn
documents-403-quota
Every operation must document the 403 quota-exhaustion response.
$.paths[*][get].responses
warn
documents-429-rate-limit
Every operation must document the 429 rate-limit response.
$.paths[*][get].responses
error
success-returns-json
A 200 must declare an application/json body.
$.paths[*][get].responses.200.content
error
api-key-scheme-declared
The Authorization header subscription key must be declared as a security scheme, not left implicit in prose.
$.components.securitySchemes
error
info-has-contact
The publishing office must be reachable from the contract.
$.info
warn
info-has-terms-of-service
Use of this data is governed by published terms; the contract must point at them.
$.info

Spectral Ruleset

Raw ↑
# authorship: generated by API Evangelist tooling. Stamped 2026-09-01.
# An unmarked file is NOT assumed to be ours.
x-method: generated
x-source: openapi/university-of-macau-open-data-api-openapi.yml
x-operator: institution
# University of Macau — Data and Open Data API Platform: Spectral ruleset.
# Plain Spectral, built-in functions only. Rules were measured from this API's own
# conventions before being written, and each one holds at 100% on the spec today.
#
# Provenance (measured 2026-09-01 over 19 operations across 19 paths):
#   - read-only-surface:         GET @ 19/19 (100%) — the platform publishes no write operation
#   - operation-id-snake-case:   19/19 (100%)
#   - operation-has-tag:         19/19 (100%)
#   - operation-has-description: 19/19 (100%)
#   - path-segment-snake-case:   23/23 non-template segments (100%)
#   - documents-401:             19/19 (100%); 400/403/404/429/500 likewise 19/19
#   - query-param-snake-case:    93/96 (97%) — the three exceptions are camelCase PATH template
#     parameters carried over from the gateway (courseCode, sectionCode, unitCode), which is why
#     the casing rule is scoped to query parameters and left at severity warn.
extends: []
rules:
  read-only-surface:
    description: >-
      Every operation on this platform is a GET. A non-GET operation would be a change in kind for
      an open-data publication surface and should be deliberate.
    severity: warn
    given: $.paths[*]
    then:
      field: put
      function: undefined
  operation-has-tag:
    description: Every operation must carry at least one tag naming its data set.
    severity: error
    given: $.paths[*][get]
    then:
      field: tags
      function: truthy
  operation-has-operation-id:
    description: Every operation must declare an operationId.
    severity: error
    given: $.paths[*][get]
    then:
      field: operationId
      function: truthy
  operation-id-snake-case:
    description: operationId follows this API's snake_case convention.
    severity: warn
    given: $.paths[*][get].operationId
    then:
      function: pattern
      functionOptions:
        match: '^[a-z0-9]+(_[a-z0-9]+)*$'
  operation-has-description:
    description: Every operation must describe what the data set contains.
    severity: warn
    given: $.paths[*][get]
    then:
      field: description
      function: truthy
  path-segment-snake-case:
    description: >-
      Path segments use lower snake_case (service/facilities/car_park_availability/all).
    severity: warn
    given: $.paths
    then:
      field: '@key'
      function: pattern
      functionOptions:
        match: '^(/[a-z0-9_]+|/\{[A-Za-z0-9]+\})+$'
  query-param-snake-case:
    description: >-
      Query parameter names use lower snake_case (date_from, course_code, sort_by). Path template
      parameters inherited from the gateway are camelCase and are deliberately out of scope.
    severity: warn
    given: $.paths[*][get].parameters[?(@.in == 'query')].name
    then:
      function: pattern
      functionOptions:
        match: '^[a-z0-9]+(_[a-z0-9]+)*$'
  parameter-has-description:
    description: Every declared parameter should say what it filters or controls.
    severity: warn
    given: $.paths[*][get].parameters[?(@.name)]
    then:
      field: description
      function: truthy
  documents-401:
    description: >-
      Every operation is subscription-key protected and must document the 401 the gateway returns
      without one.
    severity: error
    given: $.paths[*][get].responses
    then:
      field: '401'
      function: truthy
  documents-403-quota:
    description: Every operation must document the 403 quota-exhaustion response.
    severity: warn
    given: $.paths[*][get].responses
    then:
      field: '403'
      function: truthy
  documents-429-rate-limit:
    description: Every operation must document the 429 rate-limit response.
    severity: warn
    given: $.paths[*][get].responses
    then:
      field: '429'
      function: truthy
  success-returns-json:
    description: A 200 must declare an application/json body.
    severity: error
    given: $.paths[*][get].responses.200.content
    then:
      field: application/json
      function: truthy
  api-key-scheme-declared:
    description: >-
      The Authorization header subscription key must be declared as a security scheme, not left
      implicit in prose.
    severity: error
    given: $.components.securitySchemes
    then:
      field: apiKeyHeader
      function: truthy
  info-has-contact:
    description: The publishing office must be reachable from the contract.
    severity: error
    given: $.info
    then:
      field: contact
      function: truthy
  info-has-terms-of-service:
    description: >-
      Use of this data is governed by published terms; the contract must point at them.
    severity: warn
    given: $.info
    then:
      field: termsOfService
      function: truthy

Work with this as data

Every ruleset here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for spectral rules

4 MCP tools reach this
  • find_rulesBrowse and filter every ruleset in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This ruleset
curl "https://apis.io/api/v1/rules/university-of-macau-openapi-spectral-rules"
All spectral rules
curl "https://apis.io/api/v1/rules?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.