University of Helsinki · API Governance Rules

University of Helsinki — openapi rules

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

13 Rules error 5 warn 8
Derived by API Evangelist Measured from the API contracts University of Helsinki publishes — the conventions those documents already follow, written down as rules. University of Helsinki did not publish this file.
View Rules File View on GitHub

Rule Categories

api info no oauth2 operation path security server

Rules

error
server-url-absolute
Every server URL must be absolute. All thirteen University of Helsinki specs already do this, which is why none of them fell into the audit's `hostless` class — a relative or missing servers block is exactly how a vendor's contract passes as an institution's.
$.servers[*].url
error
server-on-institution-host
Server URLs must resolve to a host the University of Helsinki operates — gw.api.helsinki.fi for the gateway estate, api.laji.fi for the Finnish Museum of Natural History. A spec whose server points anywhere else does not belong in this repository.
$.servers[*].url
warn
operation-summary
Every operation should carry a summary. Met at 93%.
$.paths[*][get,put,post,delete,patch]
warn
operation-tags
Every operation should be tagged. Met at 91%.
$.paths[*][get,put,post,delete,patch]
warn
operation-operation-id
Every operation should carry an operationId. Met at 73%; the gap is concentrated in the older gateway APIs.
$.paths[*][get,put,post,delete,patch]
warn
operation-description
Every operation should carry a description as well as a summary. Met at only 25% — the largest single documentation gap in the estate, and the cheapest to close.
$.paths[*][get,put,post,delete,patch]
warn
info-description
Every spec should describe itself. Met by 5 of 13.
$.info
warn
info-contact
Every spec should name a contact. Met by 4 of 13, and where it is present the convention is a functional group address at helsinki.fi (tike-integraatiopalvelu@, grp-nxstage-devs@) rather than a named individual — that is the right convention and should be the rule.
$.info
error
security-scheme-declared
Every spec must declare at least one security scheme. The gateway has keyless access disabled, so a spec with no scheme cannot be called as written — two currently are in that state (Dawa Sync, Sovellussalkku).
$.components
warn
api-key-header-canonical
The gateway's own configuration names `X-Api-Key` as the credential header. Specs should use that exact spelling; one currently declares `X-API-Key`.
$.components.securitySchemes[?(@.type=='apiKey' && @.in=='header')].name
error
oauth2-flows-declared
An oauth2 security scheme must declare its flows. The one oauth2 scheme in the estate declares none and links a third-party CRM vendor's documentation, which is boilerplate that escaped into a published contract.
$.components.securitySchemes[?(@.type=='oauth2')]
warn
path-segment-lowercase
Path segments should be lowercase or kebab-case, the estate's dominant convention (466 of 541 segments).
$.paths
error
no-server-variables-unset
Server variables must carry a default so the URL is resolvable without out-of-band knowledge.
$.servers[*].variables[*]

Spectral Ruleset

Raw ↑
# authorship: generated by API Evangelist from the University of Helsinki's own
# published OpenAPI conventions, 2026-08-30. Nothing here is a house style
# imported from elsewhere -- every threshold below is a measurement of the
# thirteen institution-operated specs in openapi/_original/.
x-method: derived
x-source: openapi/_original/
x-operator: institution
#
# Measured across 13 specs / 320 operations / 316 component schemas:
#   servers absolute .............. 13/13  (100%)
#   operation summary ............. 297/320 (93%)
#   operation tags ................ 291/320 (91%)
#   security declared per op ...... 251/320 (78%)
#   operationId ................... 233/320 (73%)
#   operation description ......... 79/320  (25%)   <- the weak spot
#   info.description .............. 5/13    (38%)
#   info.contact .................. 4/13    (31%)
#   path segment casing ........... lower/kebab 466, snake 45, camel 20, other 10
#   property casing ............... camel 2045, lower 1372, snake 28, other 64
#
# Two rules below (operation-description, info-contact) are deliberately set at
# `warn` on conventions this estate does NOT currently meet. They are the
# remediation list, not a description of the status quo.
rules:
  server-url-absolute:
    description: >-
      Every server URL must be absolute. All thirteen University of Helsinki specs already do
      this, which is why none of them fell into the audit's `hostless` class — a relative or
      missing servers block is exactly how a vendor's contract passes as an institution's.
    severity: error
    given: $.servers[*].url
    then:
      function: pattern
      functionOptions:
        match: '^https://'
  server-on-institution-host:
    description: >-
      Server URLs must resolve to a host the University of Helsinki operates —
      gw.api.helsinki.fi for the gateway estate, api.laji.fi for the Finnish Museum of Natural
      History. A spec whose server points anywhere else does not belong in this repository.
    severity: error
    given: $.servers[*].url
    then:
      function: pattern
      functionOptions:
        match: '^https://(gw\.api\.helsinki\.fi|api\.laji\.fi)'
  operation-summary:
    description: Every operation should carry a summary. Met at 93%.
    severity: warn
    given: $.paths[*][get,put,post,delete,patch]
    then:
      field: summary
      function: truthy
  operation-tags:
    description: Every operation should be tagged. Met at 91%.
    severity: warn
    given: $.paths[*][get,put,post,delete,patch]
    then:
      field: tags
      function: truthy
  operation-operation-id:
    description: Every operation should carry an operationId. Met at 73%; the gap is concentrated in the older gateway APIs.
    severity: warn
    given: $.paths[*][get,put,post,delete,patch]
    then:
      field: operationId
      function: truthy
  operation-description:
    description: >-
      Every operation should carry a description as well as a summary. Met at only 25% — the
      largest single documentation gap in the estate, and the cheapest to close.
    severity: warn
    given: $.paths[*][get,put,post,delete,patch]
    then:
      field: description
      function: truthy
  info-description:
    description: Every spec should describe itself. Met by 5 of 13.
    severity: warn
    given: $.info
    then:
      field: description
      function: truthy
  info-contact:
    description: >-
      Every spec should name a contact. Met by 4 of 13, and where it is present the convention is
      a functional group address at helsinki.fi (tike-integraatiopalvelu@, grp-nxstage-devs@)
      rather than a named individual — that is the right convention and should be the rule.
    severity: warn
    given: $.info
    then:
      field: contact
      function: truthy
  security-scheme-declared:
    description: >-
      Every spec must declare at least one security scheme. The gateway has keyless access
      disabled, so a spec with no scheme cannot be called as written — two currently are in that
      state (Dawa Sync, Sovellussalkku).
    severity: error
    given: $.components
    then:
      field: securitySchemes
      function: truthy
  api-key-header-canonical:
    description: >-
      The gateway's own configuration names `X-Api-Key` as the credential header. Specs should use
      that exact spelling; one currently declares `X-API-Key`.
    severity: warn
    given: $.components.securitySchemes[?(@.type=='apiKey' && @.in=='header')].name
    then:
      function: pattern
      functionOptions:
        match: '^X-Api-Key$'
  oauth2-flows-declared:
    description: >-
      An oauth2 security scheme must declare its flows. The one oauth2 scheme in the estate
      declares none and links a third-party CRM vendor's documentation, which is boilerplate that
      escaped into a published contract.
    severity: error
    given: $.components.securitySchemes[?(@.type=='oauth2')]
    then:
      field: flows
      function: truthy
  path-segment-lowercase:
    description: Path segments should be lowercase or kebab-case, the estate's dominant convention (466 of 541 segments).
    severity: warn
    given: $.paths
    then:
      field: '@key'
      function: pattern
      functionOptions:
        match: '^\/([a-z0-9\-._~]+|\{[^}]+\})(\/([a-z0-9\-._~]+|\{[^}]+\}))*\/?$'
  no-server-variables-unset:
    description: Server variables must carry a default so the URL is resolvable without out-of-band knowledge.
    severity: error
    given: $.servers[*].variables[*]
    then:
      field: default
      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-helsinki-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.