Monitive Events API

The Events API from Monitive — 4 operation(s) for events.

Operations 4

POST /api/v1/events/ticket Issue a single-use SSE connection ticket #
GET /api/v1/events/stream Subscribe to the live event stream (SSE) #
POST /api/v1/admin/events/ticket Issue a single-use admin aggregate SSE ticket #
GET /api/v1/admin/events/stream Subscribe to the admin aggregate live event stream (SSE) #

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.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/uptimemonitoring-com:uptimemonitoring-com-events-api"
All apis
curl "https://apis.io/api/v1/apis?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.

OpenAPI Specification

uptimemonitoring-com-events-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: UptimeMonitoring.com Events API
  version: 0.1.0
  description: 'API-first uptime monitoring for developers, deploy pipelines, and AI agents.


    ## Authentication


    All `/api/v1` endpoints require a Bearer token — either an API key (`umk_live_*`)

    or a session token obtained via GitHub OAuth. The `/mcp` endpoint additionally

    accepts OAuth 2.1 JWT access tokens (`eyJ...`) issued via the self-hosted

    authorization server documented under the `OAuth` tag.


    ```

    Authorization: Bearer umk_live_abc123...

    ```


    ## Rate limits


    200 requests/minute per account. Exceeding the limit returns `429` with a

    `Retry-After` header.


    Responses that pass through the per-account rate-limiter carry the

    `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`

    headers (decimal integers; `Reset` is a Unix epoch second at which

    the bucket would be full again). In practice this is every

    authenticated response under `/api/v1/*` whose request reached the

    handler — earlier failures from the auth middleware (e.g. 401 missing

    credentials, 403 suspended account) return before the limiter runs

    and do NOT carry the trio. Routes mounted outside `/api/v1`

    (notably `GET /api/v1/events/stream`, which has its own SSE

    middleware stack) are not subject to this limiter and likewise do

    not emit these headers. Successful responses on

    `POST /api/v1/monitors` reflect the **global** 200/min bucket; the

    per-route 20/min creation limit only surfaces its own headers when

    it 429s. The trio is documented once here rather than referenced

    into every individual response — see `components.headers` for the

    schemas.


    One exception: once a request presenting an API key enters an

    authenticated route group through a registered route or mounted

    subtree, while that key remains in the bounded pre-auth cache

    (entries expire after 5 minutes, but may be evicted sooner once the

    cache is at capacity), the global bucket is charged BEFORE

    authentication and authorization run (issue #47) — so for that

    cached key only, a `401` (key revoked while still cached), `403`,

    `500`, or a `404` for an unmatched path inside a mounted subtree

    also carries the `X-RateLimit-*` trio and spends one token. `429`

    still comes first whenever the bucket is already empty. An uncached

    key (first seen, expired, or evicted early at capacity), a session

    token, an OAuth JWT, and any path outside every authenticated group

    are all unaffected.


    ## Browser push notifications


    Subscriptions registered via `POST /api/v1/push/subscribe` receive

    fire-and-forget Web Push notifications on monitor state transitions

    (down/up/flapping); per-monitor 5-minute throttle. No public API change

    in this release — dispatch is internal to `internal/push.Dispatcher`.'
  contact:
    name: UptimeMonitoring.com
    url: https://uptimemonitoring.com
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
- url: https://api.uptimemonitoring.com
  description: Production
tags:
- name: Events
paths:
  /api/v1/events/ticket:
    post:
      operationId: issueSSETicket
      summary: Issue a single-use SSE connection ticket
      description: 'Mints a short-lived ticket that the dashboard exchanges for an SSE

        connection at `GET /api/v1/events/stream`. Requires Bearer auth.

        Ticket TTL is 30 seconds; tickets are single-use.

        Rate limited to 20 ticket mints per minute per credential (issue

        #339 — an API key is one credential shared by every caller who

        presents it; a session/OAuth-JWT caller is bucketed per user, not

        per account).'
      tags:
      - Events
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Ticket issued.
          content:
            application/json:
              schema:
                type: object
                required:
                - ticket
                - expires_in
                properties:
                  ticket:
                    type: string
                    description: Opaque single-use token, base64url encoded.
                  expires_in:
                    type: integer
                    description: Seconds until the ticket expires.
                    example: 30
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '429':
          description: 'Per-credential ticket-mint rate limit exceeded (20

            requests/minute, fixed window, keyed the same way as the

            connection cap above — not per account). Distinct from the

            dispatcher-wide 200/min limit (`components.responses.RateLimited`)

            — this limiter only counts ticket mints. The `Retry-After`

            header gives the integer seconds until the oldest mint slides

            out of the window.

            '
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the next ticket mint is allowed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: ticket rate limit exceeded
  /api/v1/events/stream:
    get:
      operationId: subscribeSSEStream
      summary: Subscribe to the live event stream (SSE)
      description: 'Consumes a ticket from `POST /api/v1/events/ticket` and upgrades the

        HTTP response to an SSE stream (`text/event-stream`). Each frame is a

        JSON envelope with `type`, `monitor_ref`, `occurred_at`, and a

        type-specific `data` payload — `monitor_ref` is `""` for an

        account-level event (issue #412 replaced the old nullable numeric

        `monitor_id` with this always-present string). See

        `docs/SSE_LIVE_UPDATES_SPEC.md` for the four event types and their

        payloads. Heartbeat comments

        (`: heartbeat`) are emitted every 25 seconds.


        **Credential re-checked at open AND periodically while connected

        (issue #339).** A ticket''s bound credential — the account, the

        minting user, and the API key if one was presented — is re-verified

        against durable storage both when the ticket is redeemed and, once

        the stream is open, every ~30 seconds thereafter. Removing the

        minting user from the account, revoking the API key past its grace

        window, or suspending the account closes an already-open stream

        within roughly 45 seconds on a healthy connection (a 30s recheck

        interval + 5s check timeout detects the revocation and cancels the

        stream in ~35s, plus up to a further 10s write deadline for an

        in-flight write/flush to unblock and the stream to actually close)

        — not instantly, and not a hard worst case: the write deadline is

        armed only for the duration of a write+flush and cleared between

        frames, so it bounds the handler''s own blocking, not a stalled

        HTTP/2 connection writer. A transient failure (e.g. a database

        hiccup) never closes an open stream on its own; it only delays how

        soon a genuine revocation takes effect.'
      tags:
      - Events
      security: []
      parameters:
      - name: ticket
        in: query
        required: true
        schema:
          type: string
        description: Single-use ticket from `POST /api/v1/events/ticket`.
      responses:
        '200':
          description: SSE stream opened.
          content:
            text/event-stream:
              schema:
                type: string
                description: Server-Sent Events stream.
        '401':
          description: 'Missing, invalid, expired, or already-consumed ticket — or a

            ticket whose bound API key has been revoked. A ticket refused

            here for a revoked key is also consumed (burned): the same

            ticket value cannot be retried even within its remaining TTL.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: 'The ticket''s bound user is no longer a member of the account,

            or the account is suspended. Also consumes (burns) the

            ticket — it cannot be retried.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: 'Max concurrent SSE connections per credential reached (10 per

            credential — an API key, or a user for session/OAuth-JWT

            auth). This is a connection-cap rejection, not a rate-window

            rejection, so `Retry-After` is intentionally **not** set:

            retry depends on a peer disconnecting (no server-side clock

            event), and a guessed value would mislead clients into tight

            retry loops. Each API key has its own independent 10-slot

            budget shared across every caller who presents it; each

            session/OAuth-JWT user has their own independent 10-slot

            budget on the account, separate from every other user on that

            account. **This budget is shared with MCP GET `/mcp`

            streams** — REST event streams and MCP streams draw from the

            same per-credential counter, so a credential with zero open

            MCP streams can still hit this 429 if its REST streams (or

            vice versa) hold every slot. This 429''s body text is shared

            byte-for-byte with the MCP refusal. This route is mounted

            outside the `/api/v1/*` Bearer block, so the dispatcher-wide

            200/min limiter (`components.responses.RateLimited`) does not

            apply here — the connection cap is the only 429 source. A

            429 here does NOT consume the ticket — retry with the same

            one once a slot frees.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/admin/events/ticket:
    post:
      operationId: issueAdminSSETicket
      summary: Issue a single-use admin aggregate SSE ticket
      description: 'Mints a short-lived ticket scoped to the back-office aggregate

        SSE stream at `GET /api/v1/admin/events/stream` (the dot-grid

        live feed of every monitor across every account). Requires

        Bearer auth AND admin role per `auth.RequireAdmin`. Tickets

        minted here are stored in a separate ticket store from the

        per-account `/api/v1/events/ticket`; an admin ticket presented

        to `/api/v1/events/stream` returns 401 and vice versa.


        Ticket TTL is 30 seconds, single-use. Per-admin mint rate is 10

        per minute (fixed window) — half the per-account rate, since

        admins reconnect rarely. See `docs/SSE_LIVE_UPDATES_SPEC.md` §15.'
      tags:
      - Events
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Admin ticket issued.
          content:
            application/json:
              schema:
                type: object
                required:
                - ticket
                - expires_in
                properties:
                  ticket:
                    type: string
                    description: Opaque single-use admin token, base64url encoded.
                  expires_in:
                    type: integer
                    description: Seconds until the ticket expires.
                    example: 30
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          description: 'Per-admin ticket-mint rate limit exceeded (10 requests/minute,

            fixed window). The `Retry-After` header gives the integer

            seconds until the oldest mint slides out of the window.

            '
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the next ticket mint is allowed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: ticket rate limit exceeded
        '503':
          description: Admin events surface not configured on this dispatcher.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/admin/events/stream:
    get:
      operationId: subscribeAdminSSEStream
      summary: Subscribe to the admin aggregate live event stream (SSE)
      description: 'Consumes a ticket from `POST /api/v1/admin/events/ticket` and

        upgrades the response to an SSE stream that delivers every

        event published for every account. Used by the back-office

        dot-grid dashboard at `app.uptimemonitoring.com/ops` (SPEC

        §Back-Office Dashboard).


        Each frame carries the same envelope as

        `/api/v1/events/stream` (see `docs/SSE_LIVE_UPDATES_SPEC.md`

        §6 + §7); `account_handle` identifies the originating account

        (issue #412 — replaced the old numeric `account_id`).

        Heartbeat comments (`: heartbeat`) are emitted every 25 s.


        Admin membership is re-checked at stream-open time against

        the durable `admins` table — a row deleted in the 0-30s

        ticket-redeem window cannot keep a long-lived connection

        alive. **Also re-checked periodically while connected (issue

        #339):** once open, the same account/membership/key check plus

        the admin-lookup check both re-run every ~30 seconds. Removing

        the minting admin''s account membership, revoking their API key,

        suspending the account, or deleting their `admins` row closes

        an already-open admin stream within roughly 45 seconds on a

        healthy connection (detected within ~35 seconds by the recheck,

        plus up to a further 10s write deadline for an in-flight

        write/flush to unblock and the stream to actually close) — not

        instantly, not a hard worst case (the write deadline is armed

        only for the duration of a write+flush and cleared between

        frames, so a stalled HTTP/2 connection writer is not bounded by

        it), and never due to a merely transient error (e.g. a database

        hiccup), which only delays how soon a genuine revocation takes

        effect.'
      tags:
      - Events
      security: []
      parameters:
      - name: ticket
        in: query
        required: true
        schema:
          type: string
        description: Single-use admin ticket from `POST /api/v1/admin/events/ticket`.
      responses:
        '200':
          description: Admin SSE stream opened.
          content:
            text/event-stream:
              schema:
                type: string
                description: Server-Sent Events stream, multiplexed across all accounts.
        '401':
          description: 'Missing/invalid/expired admin ticket; OR admin membership

            was revoked between mint and redeem; OR admin status

            (the `admins` row) was revoked; OR a per-account ticket was

            presented to this admin route. A ticket refused for any of

            the DEFINITE reasons above (not "missing/invalid/expired")

            is also consumed (burned) — it cannot be retried.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '429':
          description: 'Max concurrent admin SSE connections reached (5 per

            admin). Connection-cap rejection, not a rate-window

            rejection — `Retry-After` is intentionally not set. Does

            NOT consume the ticket — retry with the same one once a

            slot frees.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Admin events surface not configured on this dispatcher.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      required:
      - error
      properties:
        error:
          type: string
      example:
        error: something went wrong
  responses:
    AccountSuspended:
      description: 'Account is currently suspended. On `POST /api/v1/monitors`, and on

        a `PUT /api/v1/monitors/{monitorID}` that changes `url` or `type`

        (issue #335), this can also be returned by the per-account

        port-scan heuristic when the triggering request crossed the

        port-fan threshold inside the sliding window (10 minutes by

        default; `SCAN_WINDOW`). A host-fan trip does NOT suspend the

        account — see the 429 response instead.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: account suspended; contact support
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: invalid credentials
    Forbidden:
      description: 'Authenticated but the caller is not permitted on this route.

        Body is the opaque `{"error":"forbidden"}` envelope used for

        every admin-gated 403 across the API; the same shape is used

        whether the caller is missing the admin role or the route

        otherwise denies them, so clients cannot distinguish the two.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: forbidden
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key (`umk_live_*`) or session token from OAuth exchange.

        '