overlay: 1.0.0 info: title: API Evangelist enhancements for the ThreatDown Nebula API version: 1.0.0 x-generated: '2026-08-04' x-method: generated x-source: openapi/malwarebytes-threatdown-nebula-openapi.json x-note: >- Additive OpenAPI Overlay 1.0.0 capturing API Evangelist's enrichment of the harvested ThreatDown Nebula definition. It never mutates the original file. Every action below records something the provider documents in prose (info.description, the Webhooks tag description) or that was observed live, but which the machine-readable definition itself omits — chiefly the total absence of error responses and rate-limit semantics. extends: openapi/malwarebytes-threatdown-nebula-openapi.json actions: - target: $.info description: Record provenance, licence status and the canonical spec location. update: contact: name: ThreatDown Support url: https://support.threatdown.com/hc/en-us/ x-spec-url: https://cloud.malwarebytes.com/api/v2/nebula/docs x-human-docs: https://api.threatdown.com/nebula/v1/docs x-harvested: '2026-08-04' x-harvested-by: API Evangelist x-license-status: >- No licence or terms-of-service is declared in the definition. API use is governed by https://www.threatdown.com/legal/terms-of-service/. - target: $.info description: >- Surface the rate limit that is stated in prose in info.description but is not machine-readable anywhere in the definition. update: x-rate-limit: default: 360 unit: requests interval: minute scope: per OAuth2 application algorithm: leaky bucket exceeded_status: 429 headers_documented: false negotiable: true artifact: rate-limits/malwarebytes-rate-limits.yml - target: $.info description: >- Record the error envelope observed live. The definition declares no 4xx or 5xx response on any of its 440 operations. update: x-error-envelope: media_type: application/json rfc9457: false shape: statusCode: integer error: string message: string artifact: errors/malwarebytes-problem-types.yml x-observed: >- {"statusCode":404,"error":"Not Found","message":"Route PATCH:/nebula/v1/endpoints not found"} - target: $.info description: Record the cursor pagination contract used across the search surface. update: x-pagination: style: cursor request: [next_cursor, page_size] response: [next_cursor, total_count] terminate_when: next_cursor absent or empty artifact: conventions/malwarebytes-conventions.yml - target: $.info description: >- Record that no request-idempotency mechanism exists, so job-issuing writes are not safely retryable. update: x-idempotency: supported: false header: null affected_writes: - api.v2.nebula.post.jobs - api.v2.nebula.post.jobs.bulk - api.v2.nebula.reissue.parent_jobs mitigation: >- Read back with correlation_id via api.v2.nebula.post.parent_jobs before reissuing after an ambiguous timeout. - target: $.info description: Attach the webhook event catalog derived from the Webhooks tag description. update: x-event-catalog: artifact: asyncapi/malwarebytes-threatdown-webhooks.yml transport: HTTP POST event_count: 18 signature_header: X-MWB-Signature signature_algorithm: HMAC-SHA256 retry: exponential backoff, default max 5 attempts asyncapi_published: false - target: $.components.securitySchemes.client_credentials description: >- Make the token endpoint absolute. The declared tokenUrl is the relative path "/token", which does not match the operation actually documented in the definition (POST /oauth2/token) and will not resolve in generated clients. update: x-token-url-absolute: https://api.threatdown.com/oauth2/token x-declared-token-url: /token x-actual-operation: api.oauth2.token x-defect: >- securitySchemes.client_credentials.flows.clientCredentials.tokenUrl is "/token" but the token operation in this same definition is POST /oauth2/token. Report upstream. - target: $.components.securitySchemes description: >- Document the two-gate authorization model. `user_permissions` is declared as an HTTP bearer scheme, but it is not a second credential — it is the granular permission the creating user must hold, carried in the same bearer token. update: x-authorization-model: gates: - name: oauth2 scope values: [read, write, execute] fixed_at: application creation in the console Integrate page - name: user permission distinct_values: 86 held_by: the user who created the OAuth2 application failure_status: 403 indistinguishable: >- Both gates fail with a bare 403 and no machine-readable discriminator. artifacts: - scopes/malwarebytes-scopes.yml - authentication/malwarebytes-authentication.yml - target: $.info description: >- Record the CORS posture the definition states, since it is unusual for an API that can isolate and reboot production machines. update: x-cors: enabled: true policy: wildcard same-origin on all responses quoted: >- "All responses have a wildcard same-origin which makes them completely public and accessible to everyone, including any code on any site." - target: $.info description: Record the structural review findings for this definition. update: x-api-evangelist-review: strengths: - 440 operations, every one carrying a unique operationId, a summary and a description - Per-operation security declared with both scope and granular permission - Consistent cursor pagination across the search surface - A genuinely well-documented webhook contract with HMAC verification defects: - >- No 4xx or 5xx response declared on any operation — a generated client has no error model, and an agent reading this spec would infer that every call succeeds. - >- components.schemas is empty; every schema is inlined per operation, producing a 17.8 MB document with no reusable types. - >- The `authorization` header is declared as a plain required parameter on 439 of 440 operations in addition to the securityScheme, so generated clients duplicate it. - >- tokenUrl is relative and does not match the documented token operation. - No response examples anywhere in the definition. - >- Large read operations are modelled as POST, forfeiting cacheability and HTTP safe- retry semantics.