Home
7shifts
7shifts API Rules
7shifts API Rules
Spectral linting rules defining API design standards and conventions for 7shifts.
41 Rules
error 10
warn 21
info 10
Rule Categories
delete
get
global
info
no
openapi
operation
parameter
path
paths
query
request
response
schema
security
server
servers
tag
Rules
error
info-title-required
API must have a title.
$.info
warn
info-title-prefix
Title should start with "7shifts".
$.info.title
warn
info-description-required
API must have a non-trivial description.
$.info
error
info-version-required
API must declare a version.
$.info
info
info-contact-required
API should provide contact information.
$.info
warn
openapi-version-3-1
Specs should target OpenAPI 3.1.x.
$.openapi
error
servers-defined
At least one server must be defined.
$.servers
error
servers-https
Server URLs must use HTTPS.
$.servers[*].url
info
server-7shifts-host
Production server should be api.7shifts.com.
$.servers[*].url
warn
paths-version-prefix
Resource paths should be versioned under /v2 (OAuth token is the exception).
$.paths[?(@property != '/oauth2/token' && @property != '/whoami')]~
warn
paths-snake-or-kebab-case
Path segments must be snake_case or kebab-case (no camelCase or PascalCase).
$.paths[*]~
error
paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths[*]~
error
paths-no-query-string
Paths must not contain query strings.
$.paths[*]~
error
operation-operationid-required
Every operation must have an operationId.
$.paths[*][get,post,put,patch,delete]
warn
operation-operationid-camelcase-verb
operationId should be camelCase and begin with a verb (list/get/retrieve/create/update/delete/approve/decline).
$.paths[*][get,post,put,patch,delete].operationId
warn
operation-summary-required
Every operation must have a summary.
$.paths[*][get,post,put,patch,delete]
info
operation-summary-title-case
Operation summaries should be Title Case (each significant word capitalized).
$.paths[*][get,post,put,patch,delete].summary
warn
operation-tags-required
Every operation must be tagged.
$.paths[*][get,post,put,patch,delete]
info
global-tags-defined
A global tags array should be defined.
$
info
tag-description-required
Each global tag should have a description.
$.tags[*]
warn
tag-title-case
Tags should be Title Case.
$.tags[*].name
info
parameter-description-required
Parameters should have descriptions.
$..parameters[*]
warn
parameter-snake-case
Parameter names should be snake_case (filter bracket params like start[gte] permitted).
$..parameters[?(@.in=='query' || @.in=='path')].name
info
parameter-pagination-cursor
Collection pagination should use cursor and limit parameters.
$..parameters[?(@.in=='query')].name
warn
request-body-json
Request bodies should accept application/json.
$.paths[*][post,put,patch].requestBody.content
error
response-success-required
Every operation must define at least one 2xx response.
$.paths[*][get,post,put,patch,delete].responses
warn
response-description-required
Responses must have descriptions.
$.paths[*][*].responses[*]
info
response-auth-errors
Secured operations should document 401/403 responses.
$.paths[*][get,post,put,patch,delete]
warn
schema-property-snake-case
Schema properties should be snake_case.
$.components.schemas[*].properties[*]~
info
schema-title-required
Top-level schemas should declare a title.
$.components.schemas[*]
info
schema-types-defined
Schema properties should declare a type or $ref.
$.components.schemas[*].properties[*]
error
security-schemes-defined
Security schemes must be defined.
$.components.securitySchemes
warn
security-bearer-present
A bearer (access token) security scheme should be present.
$.components.securitySchemes
error
get-no-request-body
GET operations must not declare a request body.
$.paths[*].get
warn
delete-no-request-body
DELETE operations should not declare a request body.
$.paths[*].delete
warn
path-params-casing
Path parameters should be snake_case (the dominant convention in this API).
$.paths[*].parameters[?(@.in=='path')].name
warn
query-params-casing
Query parameters should be snake_case (the dominant convention in this API).
$.paths[*][get,post,put,patch,delete].parameters[?(@.in=='query')]
warn
schema-names-casing
Component schema names should be PascalCase (the dominant convention in this API).
$.components.schemas
warn
schema-properties-casing
Schema properties should be snake_case (the dominant convention in this API).
$.components.schemas[*].properties
warn
operation-security-required
Every operation should declare its security requirements.
$.paths[*][get,post,put,patch,delete]
warn
no-empty-descriptions
Descriptions must not be empty strings.
$..description
Spectral Ruleset
# authorship: generated by API Evangelist tooling. Stamped 2026-08-18
# on the file's own generator header (roadmap#64). An unmarked file is
# NOT assumed to be ours -- absence of evidence was never stamped.
x-method: generated
# 7shifts — Spectral ruleset (strengthened)
# Plain Spectral. Existing hand-authored rules preserved; measured rules added
# from this provider's own OpenAPI conventions by strengthen_ruleset.py,
# then self-validated against the spec.
#
# Provenance:
# - servers-https-only: 100% of servers already https (error)
# - servers-expected-domain: 1/1 servers on 7shifts.com
# - path-params-casing: snake @ 100% (n=39)
# - query-params-casing: snake @ 92% (n=52)
# - operationid-casing: camel @ 100% (n=33)
# - schema-names-casing: pascal @ 100% (n=16)
# - schema-properties-casing: snake @ 100% (n=127)
# - operation-security-required: 32/33 ops declare per-op security
# - pagination params observed: ['cursor', 'limit']
# - merge: kept 35 existing, added 6 measured, upgraded 0
# - added: path-params-casing, query-params-casing, schema-names-casing, schema-properties-casing, operation-security-required, no-empty-descriptions
extends:
- spectral:oas
rules:
info-title-required:
description: API must have a title.
given: $.info
severity: error
then:
field: title
function: truthy
info-title-prefix:
description: Title should start with "7shifts".
given: $.info.title
severity: warn
then:
function: pattern
functionOptions:
match: ^7shifts
info-description-required:
description: API must have a non-trivial description.
given: $.info
severity: warn
then:
field: description
function: truthy
info-version-required:
description: API must declare a version.
given: $.info
severity: error
then:
field: version
function: truthy
info-contact-required:
description: API should provide contact information.
given: $.info
severity: info
then:
field: contact
function: truthy
openapi-version-3-1:
description: Specs should target OpenAPI 3.1.x.
given: $.openapi
severity: warn
then:
function: pattern
functionOptions:
match: ^3\.1\.
servers-defined:
description: At least one server must be defined.
given: $.servers
severity: error
then:
function: length
functionOptions:
min: 1
servers-https:
description: Server URLs must use HTTPS.
given: $.servers[*].url
severity: error
then:
function: pattern
functionOptions:
match: ^https://
server-7shifts-host:
description: Production server should be api.7shifts.com.
given: $.servers[*].url
severity: info
then:
function: pattern
functionOptions:
match: api\.7shifts\.com
paths-version-prefix:
description: Resource paths should be versioned under /v2 (OAuth token is the exception).
given: $.paths[?(@property != '/oauth2/token' && @property != '/whoami')]~
severity: warn
then:
function: pattern
functionOptions:
match: ^/v2/
paths-snake-or-kebab-case:
description: Path segments must be snake_case or kebab-case (no camelCase or PascalCase).
given: $.paths[*]~
severity: warn
then:
function: pattern
functionOptions:
match: ^(/[a-z0-9_\-]+|/\{[a-z0-9_]+\})*/?$
paths-no-trailing-slash:
description: Paths must not end with a trailing slash.
given: $.paths[*]~
severity: error
then:
function: pattern
functionOptions:
notMatch: .+/$
paths-no-query-string:
description: Paths must not contain query strings.
given: $.paths[*]~
severity: error
then:
function: pattern
functionOptions:
notMatch: \?
operation-operationid-required:
description: Every operation must have an operationId.
given: $.paths[*][get,post,put,patch,delete]
severity: error
then:
field: operationId
function: truthy
operation-operationid-camelcase-verb:
description: operationId should be camelCase and begin with a verb (list/get/retrieve/create/update/delete/approve/decline).
given: $.paths[*][get,post,put,patch,delete].operationId
severity: warn
then:
function: pattern
functionOptions:
match: ^(list|get|retrieve|create|update|put|delete|approve|decline|sync|test|configure|save|fetch|deactivate)[A-Za-z0-9]*$
operation-summary-required:
description: Every operation must have a summary.
given: $.paths[*][get,post,put,patch,delete]
severity: warn
then:
field: summary
function: truthy
operation-summary-title-case:
description: Operation summaries should be Title Case (each significant word capitalized).
given: $.paths[*][get,post,put,patch,delete].summary
severity: info
then:
function: pattern
functionOptions:
match: ^[A-Z]
operation-tags-required:
description: Every operation must be tagged.
given: $.paths[*][get,post,put,patch,delete]
severity: warn
then:
field: tags
function: truthy
global-tags-defined:
description: A global tags array should be defined.
given: $
severity: info
then:
field: tags
function: truthy
tag-description-required:
description: Each global tag should have a description.
given: $.tags[*]
severity: info
then:
field: description
function: truthy
tag-title-case:
description: Tags should be Title Case.
given: $.tags[*].name
severity: warn
then:
function: pattern
functionOptions:
match: ^[A-Z][A-Za-z0-9]*( [A-Z][A-Za-z0-9]*)*$
parameter-description-required:
description: Parameters should have descriptions.
given: $..parameters[*]
severity: info
then:
field: description
function: truthy
parameter-snake-case:
description: Parameter names should be snake_case (filter bracket params like start[gte] permitted).
given: $..parameters[?(@.in=='query' || @.in=='path')].name
severity: warn
then:
function: pattern
functionOptions:
match: ^[a-z][a-z0-9_]*(\[[a-z]+\])?$
parameter-pagination-cursor:
description: Collection pagination should use cursor and limit parameters.
given: $..parameters[?(@.in=='query')].name
severity: info
then:
function: pattern
functionOptions:
match: .*
request-body-json:
description: Request bodies should accept application/json.
given: $.paths[*][post,put,patch].requestBody.content
severity: warn
then:
field: application/json
function: truthy
response-success-required:
description: Every operation must define at least one 2xx response.
given: $.paths[*][get,post,put,patch,delete].responses
severity: error
then:
function: schema
functionOptions:
schema:
type: object
patternProperties:
^2[0-9][0-9]$: {}
minProperties: 1
response-description-required:
description: Responses must have descriptions.
given: $.paths[*][*].responses[*]
severity: warn
then:
field: description
function: truthy
response-auth-errors:
description: Secured operations should document 401/403 responses.
given: $.paths[*][get,post,put,patch,delete]
severity: info
then:
function: defined
schema-property-snake-case:
description: Schema properties should be snake_case.
given: $.components.schemas[*].properties[*]~
severity: warn
then:
function: pattern
functionOptions:
match: ^[a-z][a-z0-9_]*$|^(in|out)$
schema-title-required:
description: Top-level schemas should declare a title.
given: $.components.schemas[*]
severity: info
then:
field: title
function: truthy
schema-types-defined:
description: Schema properties should declare a type or $ref.
given: $.components.schemas[*].properties[*]
severity: info
then:
function: defined
security-schemes-defined:
description: Security schemes must be defined.
given: $.components.securitySchemes
severity: error
then:
function: truthy
security-bearer-present:
description: A bearer (access token) security scheme should be present.
given: $.components.securitySchemes
severity: warn
then:
field: bearerAuth
function: truthy
get-no-request-body:
description: GET operations must not declare a request body.
given: $.paths[*].get
severity: error
then:
field: requestBody
function: undefined
delete-no-request-body:
description: DELETE operations should not declare a request body.
given: $.paths[*].delete
severity: warn
then:
field: requestBody
function: undefined
path-params-casing:
description: Path parameters should be snake_case (the dominant convention in this API).
severity: warn
given: $.paths[*].parameters[?(@.in=='path')].name
then:
function: casing
functionOptions:
type: snake
query-params-casing:
description: Query parameters should be snake_case (the dominant convention in this API).
severity: warn
given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in=='query')]
then:
field: name
function: casing
functionOptions:
type: snake
schema-names-casing:
description: Component schema names should be PascalCase (the dominant convention in this API).
severity: warn
given: $.components.schemas
then:
field: '@key'
function: pattern
functionOptions:
match: ^[A-Z][A-Za-z0-9]*$
schema-properties-casing:
description: Schema properties should be snake_case (the dominant convention in this API).
severity: warn
given: $.components.schemas[*].properties
then:
field: '@key'
function: casing
functionOptions:
type: snake
operation-security-required:
description: Every operation should declare its security requirements.
severity: warn
given: $.paths[*][get,post,put,patch,delete]
then:
field: security
function: truthy
no-empty-descriptions:
description: Descriptions must not be empty strings.
severity: warn
given: $..description
then:
function: truthy
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/7shifts-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.