Work with this as data
Every API 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 apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.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.
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/ismalicious-com:ismalicious-com-alerts-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
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.
OpenAPI Specification
openapi: 3.2.0
info:
title: Ismalicious Com Alerts API
version: 1.2.0
contact:
name: isMalicious Support
url: https://ismalicious.com/support
email: contact@ismalicious.com
license:
name: Proprietary
url: https://ismalicious.com/terms
description: 'Operations tagged alerts across 2 of this provider''s published API definitions: ismalicious-com-openapi.json, ismalicious-com-openapi2.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.ismalicious.com
description: Production server
security:
- ApiKeyAuth: []
- BearerAuth: []
- BasicAuth: []
tags:
- name: Alerts
description: Alerting trends and metrics
paths:
/alerts/trends:
get:
tags:
- Alerts
operationId: getAlertTrends
parameters:
- name: days
in: query
description: Window in days (7-90, default 30)
required: false
schema:
type: integer
format: int64
responses:
'200':
description: Opened/resolved per day plus MTTR percentiles for the signed-in scope
content:
application/json:
schema:
$ref: '#/components/schemas/AlertTrendsResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
summary: Get alert trends
x-summary-source: derived
servers:
- url: https://api.ismalicious.com
description: Production server
/alerts/{id}:
patch:
tags:
- Alerts
summary: Set an alert's status
description: '`OPEN`, `ACKNOWLEDGED` or `RESOLVED`, on one of your alerts (`GET
/alerts`). Most alerts are per person: the write changes your copy only.
A `cve.finding` alert of your organization and its Surveillance finding
are one: `ACKNOWLEDGED` acknowledges an open finding, `RESOLVED` marks a
finding that is not closed `PATCHED`, `OPEN` reopens one — for the whole
organization, every member''s copy of the alert following, and
`cve.finding.status_changed` is sent. When the finding does not move, the
alert takes the finding''s status back (`finding` in the answer says which).
With an API key the write is the organization''s automation: the finding
names no person and the webhook carries `actor: "api"`; with a session it
names you and says `actor: "user"`.'
operationId: updateAlertStatus
parameters:
- name: id
in: path
description: The alert id (`GET /alerts`)
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAlertRequest'
required: true
responses:
'200':
description: The alert as the write left it, and for a `cve.finding` alert its finding
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAlertResponse'
'400':
description: '`{"error": "Invalid status. Valid statuses are OPEN, ACKNOWLEDGED, RESOLVED."}`'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: '`{"error": "Alert not found"}`: no alert of yours with this id'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
servers:
- url: https://api.ismalicious.com
description: Production server
/stream:
get:
tags:
- Alerts
summary: Alert stream (SSE)
description: 'Your **new alerts**, as Server-Sent Events: the alerts of `GET /alerts`
that belong to your current organization — the inbox of the session''s
user, or of the organization''s owner for an API key, in the same JSON. An
older alert filed under no organization, or under one you have left, is
listed by `GET /alerts` and never streamed. Nothing else is streamed: no
corpus-wide feed (that is TAXII), no single-check progress (that is
`/check/stream`).
**Plan.** Pro and Enterprise. Free and Basic get `403` with
`error: "UPGRADE_REQUIRED"` and an offer (`cta`); a paid plan whose
payment needs attention gets `403` with `error: "BILLING_ISSUE"`.
**Cost.** Opening a stream never counts against the monthly request
quota; the key''s burst limit applies.
**Bounds.** At most 3 open streams per organization (`429`,
`{"error": "Too many streams", "limit": 3}`, `Retry-After`); 30 minutes
per connection, then `event: close` (`reason: max_duration`; also
`unavailable` after three failed or timed-out reads, and `shutdown` when
the server restarts, for a deploy: reconnect at once); a `: keep-alive`
comment every 25 s; new alerts are read every 10 s, at most 100 a read,
2 s behind the clock.
**Wire format.** `event: connect` first, its `data` carrying
`{"id":"connect","type":"connect","timestamp","data":{"details":{"organizationId","userId","filters","resumedFrom","maxDurationSeconds","pollSeconds","keepAliveSeconds"}}}`.
Then one `event: alert` per alert, with `id: -`
and `data: {"id": , "type": , "timestamp": ,
"data": {"entity", "entityType", "severity", "details": }}`. `connect`, `reset` and `close` carry
`id: -`, a bare position: where the stream started, or where its
next read would have begun.
**Resume.** Send the last `id` you received as `Last-Event-ID` (or
`?lastEventId=`) — an alert''s, or the bare position of a `connect`,
`reset` or `close`, so a client that received no alert still resumes
without a gap: the stream replays what came after it, up to 24 hours
back and 500 alerts. Past either, for an id this stream did not send, or
for one dated in the future, it sends `event: reset` (`reason`:
`cursor_expired`, `too_many_events`, `cursor_invalid`; `since`: where the
replay starts), then the latest alerts of the window — catch up on the
rest with `GET /alerts`. Delivery is at least once, in `createdAt` order
within a read: each read looks back 30 s for rows committed late, and a
resume from a `close` may repeat the alerts of its last 30 s, so
deduplicate on `data.id`.'
operationId: alertStream
parameters:
- name: types
in: query
description: 'Comma-separated alert event types (`threat.detected`,
`reputation.changed`, `monitor.alert`, `cve.finding`, … — the
`eventType` values of `GET /alerts`). Default: every type. An unknown
type answers 400.'
required: false
schema:
type: string
example: threat.detected,reputation.changed
- name: severity
in: query
description: 'Minimum severity: `low`, `medium`, `high` or `critical`. Default: every
severity.'
required: false
schema:
type: string
example: high
- name: lastEventId
in: query
description: 'Resume after this event id, for a client that cannot set the
`Last-Event-ID` header (which wins when both are sent).'
required: false
schema:
type: string
example: 1762560000123456-ck9x2abc
- name: Last-Event-ID
in: header
description: Resume after this event id
required: false
schema:
type:
- string
- 'null'
responses:
'200':
description: SSE stream — frame contract in the operation description
headers:
cache-control:
schema:
type: string
description: Always `no-cache, no-transform`
x-accel-buffering:
schema:
type: string
description: Always `no` (disables proxy buffering)
content:
text/event-stream:
schema:
type: string
'400':
description: '`{"error": "unsupported_parameter", "parameter"}`: `categories` (an alert has none), an unknown type or severity'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: No valid API key or session
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: 'Plan without the stream: `UPGRADE_REQUIRED` (Free, Basic) or `BILLING_ISSUE` (paid plan suspended), with a `cta`'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: 'Three streams already open for the organization (`Retry-After: 30`), or the key''s burst limit'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: 'Alerts could not be read when the stream opened, or this server already holds as many streams as it serves (`Retry-After: 30`); retry with the same `Last-Event-ID`'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- ApiKeyAuth: []
- BearerAuth: []
- BasicAuth: []
servers:
- url: https://api.ismalicious.com
description: Production server
components:
schemas:
ErrorResponse:
type: object
description: Error response. Some handlers return only `error`.
required:
- error
properties:
error:
type: string
description: Error type
example: Bad Request
message:
type:
- string
- 'null'
description: Detailed error message (not always present)
example: 'Missing required parameter: query'
UpdatedAlertFinding:
type: object
description: The finding a `cve.finding` alert moved (or left as it was)
required:
- id
- status
properties:
id:
type: string
example: xfnd_9f2c1e
status:
type: string
description: 'The finding''s status after the write: `OPEN`, `ACKNOWLEDGED`,
`SNOOZED`, `PATCHED`, `FIXED`, `NOT_AFFECTED`, `ACCEPTED_RISK`'
example: PATCHED
AlertTrendsMttr:
type: object
description: MTTR percentiles in hours
required:
- avgHours
- medianHours
- p95Hours
properties:
avgHours:
type: number
format: double
medianHours:
type: number
format: double
p95Hours:
type: number
format: double
AlertTrendsResponse:
type: object
description: GET /alerts/trends response (`api/alerts.rs::trends`)
required:
- days
- bucket
- timeSeries
- mttr
- totals
properties:
bucket:
type: string
description: Bucket size — always `day`
example: day
days:
type: integer
format: int64
description: Effective window in days (clamped to 7-90)
mttr:
$ref: '#/components/schemas/AlertTrendsMttr'
timeSeries:
type: array
items:
$ref: '#/components/schemas/AlertTrendPoint'
totals:
$ref: '#/components/schemas/AlertTrendsTotals'
AlertTrendPoint:
type: object
description: One day bucket of the alert trends time series
required:
- time
- opened
- resolved
properties:
opened:
type: integer
format: int64
description: Alerts opened that day
resolved:
type: integer
format: int64
description: Alerts resolved that day
time:
type: string
description: Day bucket start (RFC 3339)
example: '2026-08-01T00:00:00+00:00'
UpdateAlertRequest:
type: object
description: PATCH /alerts/{id} body (`api/alerts.rs::update_status`)
required:
- status
properties:
status:
type: string
description: '`OPEN`, `ACKNOWLEDGED` or `RESOLVED`'
example: ACKNOWLEDGED
AlertTrendsTotals:
type: object
description: Alert trends totals over the window
required:
- opened
- resolved
properties:
opened:
type: integer
format: int64
resolved:
type: integer
format: int64
UpdateAlertResponse:
type: object
description: 'PATCH /alerts/{id} response: the alert as the write left it'
required:
- id
- status
properties:
acknowledgedAt:
type:
- string
- 'null'
finding:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/UpdatedAlertFinding'
description: '`null` unless the alert is a `cve.finding` alert of your organization'
id:
type: string
resolvedAt:
type:
- string
- 'null'
status:
type: string
description: 'The alert''s status after the write. For a `cve.finding` alert it is
the finding''s (`finding.status`), which may differ from the one asked
for: « ACKNOWLEDGED » on a patched finding stays `RESOLVED`'
example: ACKNOWLEDGED
updatedAt:
type:
- string
- 'null'
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-KEY
description: Base64 encoded `apiKey:apiSecret`. Get your keys from https://ismalicious.com/app/account
BasicAuth:
type: http
scheme: basic
description: 'Username = apiKey, password = apiSecret. Legacy: any username, password = Base64(apiKey:apiSecret).'
BearerAuth:
type: http
scheme: bearer
description: '`Authorization: Bearer <token>` where token = Base64(apiKey:apiSecret) — the same credential as X-API-KEY.'
sessionCookie:
type: apiKey
in: cookie
name: __Secure-authjs.session-token
description: Authenticated browser session. The claim endpoint also requires a verified email in the database; organization API keys cannot claim watches.
x-refined-from:
- ismalicious-com-openapi.json
- ismalicious-com-openapi2.json