extends: - spectral:oas # Spectral ruleset for the AMC Theatres API. # Reflects conventions observed in developers.amctheatres.com: # - Resources are under /v1, /v2, /v3, /v4 prefixes per resource family # - Auth is via the X-AMC-Vendor-Key header (apiKey) # - Collection responses use HAL-style _embedded + pageSize/pageNumber/count # - Path segments and query parameter names use kebab-case # - operationIds use camelCase # - tags use Title Case rules: # ============================================================= # INFO / METADATA # ============================================================= amc-info-title-required: description: API title must be present. severity: error given: $.info then: field: title function: truthy amc-info-title-format: description: Title should start with "AMC". severity: warn given: $.info.title then: function: pattern functionOptions: match: "^AMC " amc-info-description-min-length: description: API description should be substantive (>= 80 chars). severity: warn given: $.info.description then: function: length functionOptions: min: 80 amc-info-contact-required: description: Contact information must be provided. severity: warn given: $.info then: field: contact function: truthy amc-info-license-required: description: License must be declared (AMC API Terms of Use). severity: warn given: $.info then: field: license function: truthy # ============================================================= # SERVERS # ============================================================= amc-servers-required: description: At least one server must be defined. severity: error given: $ then: field: servers function: truthy amc-servers-amctheatres-host: description: Server URL must point at api.amctheatres.com. severity: error given: $.servers[*].url then: function: pattern functionOptions: match: "^https://api\\.amctheatres\\.com" amc-servers-https-only: description: AMC API only supports HTTPS. severity: error given: $.servers[*].url then: function: pattern functionOptions: match: "^https://" # ============================================================= # SECURITY # ============================================================= amc-security-vendor-key-defined: description: A vendor-key apiKey security scheme must be defined. severity: error given: $.components.securitySchemes then: field: VendorKey function: truthy amc-security-vendor-key-header: description: Vendor key must be provided in the X-AMC-Vendor-Key header. severity: error given: $.components.securitySchemes.VendorKey then: - field: type function: pattern functionOptions: match: "^apiKey$" - field: in function: pattern functionOptions: match: "^header$" - field: name function: pattern functionOptions: match: "^X-AMC-Vendor-Key$" amc-security-applied-globally: description: The vendor-key security requirement must be applied globally. severity: error given: $ then: field: security function: truthy # ============================================================= # PATHS # ============================================================= amc-paths-versioned: description: All paths must be versioned (/v1, /v2, /v3, /v4). severity: error given: $.paths.*~ then: function: pattern functionOptions: match: "^/v[1-4](/|$)" amc-paths-kebab-case: description: Path segments (excluding parameters) must be kebab-case. severity: warn given: $.paths.*~ then: function: pattern functionOptions: match: "^(/v[1-4])(/(\\{[a-zA-Z][a-zA-Z0-9_-]*\\}|[a-z][a-z0-9-]*))*/?$" amc-paths-no-trailing-slash: description: Paths should not end with a trailing slash (except documented order email lookup). severity: warn given: $.paths.*~ then: function: pattern functionOptions: notMatch: "[a-z0-9}]/$" # ============================================================= # OPERATIONS # ============================================================= amc-operation-operationId-required: description: Every operation must declare an operationId. severity: error given: $.paths[*][get,post,put,delete,patch] then: field: operationId function: truthy amc-operation-operationId-camelcase: description: operationId must be camelCase. severity: warn given: $.paths[*][get,post,put,delete,patch].operationId then: function: pattern functionOptions: match: "^[a-z][a-zA-Z0-9]*$" amc-operation-summary-required: description: Every operation must have a summary. severity: error given: $.paths[*][get,post,put,delete,patch] then: field: summary function: truthy amc-operation-summary-title-case: description: Summary should use Title Case. severity: warn given: $.paths[*][get,post,put,delete,patch].summary then: function: pattern functionOptions: match: "^([A-Z][a-zA-Z0-9]*)( ([A-Z][a-zA-Z0-9]*|[a-z]{1,3}|By|For|To|And|Or|In|On|Of))*$" amc-operation-tags-required: description: Every operation must have at least one tag. severity: warn given: $.paths[*][get,post,put,delete,patch] then: field: tags function: truthy amc-operation-tag-titlecase: description: Tag names use Title Case (e.g., Theatres, Showtimes, Loyalty). severity: warn given: $.paths[*][get,post,put,delete,patch].tags[*] then: function: pattern functionOptions: match: "^[A-Z][a-zA-Z]*$" amc-operation-200-response: description: Read operations should declare a 200 response. severity: warn given: $.paths[*].get.responses then: field: '200' function: truthy amc-operation-201-on-create: description: POST operations that create resources should return 201. severity: info given: "$.paths[?(@property.match(/orders|webhooks|registration|redemptions/))].post.responses" then: field: '201' function: truthy # ============================================================= # PARAMETERS # ============================================================= amc-parameter-name-kebab-case: description: Query and path parameter names should use kebab-case (page-size, theatre-number, etc.). severity: warn given: "$..parameters[?(@.in == 'query' || @.in == 'path')].name" then: function: pattern functionOptions: match: "^[a-z][a-z0-9]*(-[a-z0-9]+)*$" amc-parameter-pagination-pair: description: When page-size is used, page-number should also be available. severity: info given: "$.paths[*][get]" then: function: schema functionOptions: schema: type: object # ============================================================= # SCHEMAS # ============================================================= amc-schemas-collection-envelope: description: Collection schemas should include pageSize, pageNumber, count, and _embedded. severity: info given: $.components.schemas[?(@property.match(/Collection$/))].allOf[0] then: function: truthy amc-schemas-hal-links: description: Resources should expose HAL-style _links where applicable. severity: info given: $.components.schemas then: field: HalLinks function: truthy amc-schemas-property-camelcase: description: Schema properties should use camelCase. severity: warn given: $.components.schemas[*].properties.*~ then: function: pattern functionOptions: match: "^[a-z][a-zA-Z0-9]*$" # ============================================================= # RESPONSES # ============================================================= amc-responses-error-content: description: Error responses should reference the ApiError schema. severity: info given: "$.components.responses.NotFound.content['application/json'].schema" then: field: $ref function: truthy