From d8b2d3284812867b2cf9b20c993e37980370ef94 Mon Sep 17 00:00:00 2001 From: "amilisic@whispir.com" Date: Tue, 17 Feb 2026 13:35:54 +1100 Subject: [PATCH 1/2] feat(CORE-2160): Removed references to 'attachments' from docs and examples and replaced with 'attachment' since this keyword produces consistent API behaviour Committed by Whispir-Softwares on behalf of amilisic@whispir.com --- .spectral.yml | 3 - .stoplight/.spectral.yml_original | 450 +----------------------------- openapi.yaml | 43 +-- 3 files changed, 23 insertions(+), 473 deletions(-) delete mode 100644 .spectral.yml diff --git a/.spectral.yml b/.spectral.yml deleted file mode 100644 index e90b8db..0000000 --- a/.spectral.yml +++ /dev/null @@ -1,3 +0,0 @@ - -rules: {} - diff --git a/.stoplight/.spectral.yml_original b/.stoplight/.spectral.yml_original index d5bed2a..e90b8db 100644 --- a/.stoplight/.spectral.yml_original +++ b/.stoplight/.spectral.yml_original @@ -1,451 +1,3 @@ -extends: spectral:oas -functions: - - oasOpIdFormat - - oasOpSdk +rules: {} -aliases: - Operation_List_Schema: - description: The schema of all operations that list resources, e.g. GET /resources - targets: - - formats: - - oas3 - given: - - "#Operation_List.responses[?(@property >= 200 && @property < 300)].content[*].schema" - Operation_List: - description: All operations that list resources, e.g. `GET /resources` - targets: - - formats: - - oas3 - given: - - "$.paths[?(!(@property).endsWith('}'))].get" - -rules: - openapi-tags-alphabetical: off - operation-success-response: error - oas2-operation-formData-consume-check: error - operation-parameters: error - operation-tag-defined: error - contact-properties: error - duplicated-entry-in-enum: error - info-contact: error - info-description: error - info-license: error - license-url: error - no-eval-in-markdown: error - no-script-tags-in-markdown: error - openapi-tags: error - operation-description: error - operation-operationId: error - operation-operationId-valid-in-url: error - operation-singular-tag: error - operation-tags: error - path-declarations-must-exist: error - path-keys-no-trailing-slash: error - path-not-include-query: error - tag-description: error - typed-enum: error - oas2-api-host: error - oas2-api-schemes: error - oas2-host-not-example: error - oas2-host-trailing-slash: error - oas2-parameter-description: error - oas2-operation-security-defined: error - oas2-anyOf: error - oas2-oneOf: error - oas2-unused-definition: error - oas3-api-servers: error - oas3-examples-value-or-externalValue: error - oas3-operation-security-defined: error - oas3-parameter-description: error - oas3-server-not-example.com: error - oas3-server-trailing-slash: error - oas3-unused-component: error - - ### CORE RULES ### - schema-examples: - description: Schemas must have non-empty "x-examples" object. - severity: error - given: $.components.schemas[*] - then: - field: x-examples - function: schema - functionOptions: - dialect: draft7 - schema: - type: object - minProperties: 1 - schema-descriptions: - description: Schemas must have a "description". - severity: error - given: - - $..schemas[*] - - $..responses[*].content[*]..schema - - $..requestBody.content[*]..schema - then: - field: description - function: truthy - schema-property-descriptions: # Note: this rule is not de-duplicated, and will show on parents $ref'ing children with issues until all child issues are resolved. - description: Schema properties must have a "description". - severity: error - given: - - $..schema[*]..properties[*] - - $..responses[*].content[*]..schema..properties[*] - - $..requestBody.content[*]..schema..properties[*] - - $..headers[*] - then: - field: description - function: truthy - schema-property-examples: # Note: this rule is not de-duplicated, and will show on parents $ref'ing children with issues until all child issues are resolved. - description: Schema properties must have an "example". - severity: error - given: - - $..schema[*]..properties[?(@ && @.type && @.type !== "array" && @.type !== "object" && @.type !== "boolean" && !@.enum)] - - $..responses[*].content[*]..schema..properties[?(@ && @.type && @.type !== "array" && @.type !== "object" && @.type !== "boolean" && !@.enum)] - - $..requestBody.content[*]..schema..properties[?(@ && @.type && @.type !== "array" && @.type !== "object" && @.type !== "boolean" && !@.enum)] - - $..headers[?(@ && @.type && @.type !== "array" && @.type !== "object" && @.type !== "boolean" && !@.enum)] - then: - field: example - function: defined - payload-examples: - description: Request & response payload content must have non-empty "examples" object. - severity: error - given: - - $..responses[*].content[*] - - $..requestBody.content[*] - then: - field: examples - function: schema - functionOptions: - dialect: draft7 - schema: - type: object - minProperties: 1 - - ### API SPECIFIC RULES ### - required-all-request-headers: - given: - - "$.paths[*][get,put,post,delete,options,head,patch,trace]" - severity: error - then: - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^X-Api-Key$" - field: parameters - description: 'All requests must have the following headers "parameters": "X-Api-Key".' - required-read-request-headers: - given: - - "$.paths[*][get]" - severity: error - then: - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^Accept$" - field: parameters - description: 'Read requests must have the following headers "parameters": "Accept".' - required-write-request-headers: - given: - - "$.paths[*][put,post]" - severity: error - then: - - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^Content-Type$" - field: parameters - - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^Accept$" - field: parameters - description: - 'Write requests must have the following headers "parameters": "Content-Type", - "Accept".' - required-list-pagination-request-query-parameters: - given: - - "$.paths[?(!/{.*Id}$/i.test(@property))]['get']" - severity: error - then: - - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^limit$" - field: parameters - - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^offset$" - field: parameters - - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^sortOrder$" - field: parameters - - function: schema - functionOptions: - dialect: draft7 - schema: - type: array - contains: - type: object - properties: - name: - type: string - pattern: "^sortFields$" - field: parameters - description: - 'Read list requests must have the following query "parameters": "limit", - "offset", "sortOrder", "sortFields".' - required-all-response-headers: - given: - - "$..responses[*]" - severity: error - then: - function: schema - functionOptions: - dialect: draft7 - schema: - type: object - required: - - Access-Control-Allow-Origin - - Expires - - Cache-Control - field: headers - description: - 'All responses must have the following "headers": "Access-Control-Allow-Origin", - "Expires", "Cache-Control".' - required-content-response-headers: - given: - - "$.paths[*]..responses[?(@property != 204)]" - severity: error - then: - function: schema - functionOptions: - dialect: draft7 - schema: - type: object - required: - - Content-Type - - Content-Length - field: headers - description: - 'Responses with content must have the following "headers": "Content-Type", - "Content-Length".' - required-post-response-headers: - given: - - "$.paths[*][post]..responses[?(@property != 204 && @property >= 200 && @property - < 300)]" - severity: error - then: - function: schema - functionOptions: - dialect: draft7 - schema: - type: object - required: - - Location - field: headers - description: - 'Successful post endpoint responses must have the following "headers": - "Location".' - operation-sdkOperation-format: - given: - - "$" - severity: error - then: - function: oasOpSdk - functionOptions: - exceptions: [] - description: |- - All operations must include an "x-sdkOperation" vendor extension for use in human-readable SDK method names. - - Must start with one of the following values, corresponding to the operation on the resource: - * `create` - `POST /resource` - * `retrieve` - `GET /resource/{resourceId}` - * `update` - `PUT /resource/{resourceId}` - * `delete` - `DELETE /resource/{resourceId}` - * `list` - `GET /resource` - - An optional noun suffix describing any sub-resources may be included as appropriate. - - **Valid Example** - - ```json - { - "x-sdkOperation": "create" - } - // OR - { - "x-sdkOperation": "listWebhookCalls" - } - ``` - - **Invalid Example** - - ```json - { - "x-sdkOperation": "post" - } - // OR - { - "x-sdkOperation": "getWebhookCalls" - } - ``` - message: "{{error}}" - operation-operationId-format: - given: - - "$" - severity: error - then: - function: oasOpIdFormat - functionOptions: - exceptions: [] - description: |- - All operations must include an appropriately named "operationId". - - Must end with one of the following values, corresponding to the operation on the - resource: - * `Create` - `POST /resource` - * `Retrieve` - `GET /resource/{resourceId}` - * `Update` - `PUT /resource/{resourceId}` - * `Delete` - `DELETE /resource/{resourceId}` - * `List` - `GET /resource` - - An optional noun prefix describing any sub-resources - may be included as appropriate. - - **Valid Example** - - ```json - { - "operationId": "messageCreate" - } - // OR - { - "operationId": "webhookCallList" - } - ``` - - **Invalid Example** - - ```json - { - "operationId": "getMessage" - } - // OR - { - "operationId": "getWebhookCalls" - } - ``` - message: "{{error}}" - operation-list-schema-keys: - given: - - "#Operation_List_Schema" - severity: error - then: - function: pattern - functionOptions: - match: Collection$ - field: "$ref" - description: List operation response schema must have key ending with "Collection". - message: List operation response schema must have key ending with "Collection". - operation-list-schema-title: - given: - - "#Operation_List_Schema" - severity: error - then: - function: pattern - functionOptions: - match: Collection$ - field: title - description: |- - List operation response schema must have title ending with "Collection". - - **Valid Example** - - ```json - { - "title": "Message Collection" - } - // OR - { - "title": "Webhook Call Collection" - } - ``` - - **Invalid Example** - - ```json - { - "title": "Message List Response" - } - // OR - { - "title": "Webhook Call List" - } - ``` - message: List operation response schema must have title ending with "Collection". -overrides: - - files: - - "**#/paths/~1auth~1verify/get" - rules: - required-list-pagination-request-query-parameters: "off" - - files: - - "**#/paths/~1auth~1verify/get/operationId" - rules: - operation-operationId-format: "off" - - files: - - "**#/paths/~1auth~1verify/get/x-sdkOperation" - rules: - operation-sdkOperation-format: "off" diff --git a/openapi.yaml b/openapi.yaml index 1e5f19d..d6a2b9a 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -7256,12 +7256,14 @@ components: footer: This is the footer of my message type: text/html resources: - attachments: + attachment: - attachmentName: sample.json attachmentDesc: Sample derefUri: eyAKICAgICJzYW1wbGUiOiB0cnVlCn0= x-tags: - Messages + required: + - body properties: body: type: string @@ -7282,8 +7284,6 @@ components: $ref: '#/components/schemas/OptOutOption' resources: $ref: '#/components/schemas/Attachments' - required: - - body Voice: type: object title: Voice @@ -7631,11 +7631,23 @@ components: type: object description: The resources to attach to the Message. title: Attachments + x-tags: + - Messages + x-examples: + Image: + attachment: + - attachmentName: TestIcon.png + derefUri: iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg== + attachmentDesc: My photo + JSON: + attachment: + - attachmentName: sample.json + attachmentDesc: Sample + derefUri: eyAKICAgICJzYW1wbGUiOiB0cnVlCn0= properties: - attachments: + attachment: description: A list of attachments to attach to the Message. type: array - uniqueItems: false items: type: object description: |- @@ -7643,6 +7655,11 @@ components: Attachments must be provided in the payload of the message. URLs can be referenced in the email but will not be added as message attachments. title: Attachment + x-stoplight: + id: jh33wbnmtaz7g + required: + - attachmentName + - derefUri properties: attachmentName: type: string @@ -7656,23 +7673,7 @@ components: type: string description: A description for the attachment. example: My photo - required: - - attachmentName - - derefUri writeOnly: true - x-tags: - - Messages - x-examples: - Image: - attachments: - - attachmentName: TestIcon.png - derefUri: iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg== - attachmentDesc: My photo - JSON: - attachments: - - attachmentName: sample.json - attachmentDesc: Sample - derefUri: eyAKICAgICJzYW1wbGUiOiB0cnVlCn0= DeliveryReceipt: title: Delivery Receipt description: A fixed object structure used by for Whispir internally for tracking purposes. From 7975bb90619fb4892cacdbf5af723c140d806503 Mon Sep 17 00:00:00 2001 From: "amilisic@whispir.com" Date: Tue, 17 Feb 2026 13:54:15 +1100 Subject: [PATCH 2/2] feat(CORE-2160): Added .spectral.yml Committed by Whispir-Softwares on behalf of amilisic@whispir.com --- .spectral.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .spectral.yml diff --git a/.spectral.yml b/.spectral.yml new file mode 100644 index 0000000..3b7c80b --- /dev/null +++ b/.spectral.yml @@ -0,0 +1 @@ +rules: {} \ No newline at end of file