Monitive Push API

The Push API from Monitive — 4 operation(s) for push.

Operations 4

POST /api/v1/push/subscribe Register a browser Web Push subscription #
DELETE /api/v1/push/subscribe/{subscriptionID} Revoke a browser Web Push subscription #
GET /api/v1/push/subscriptions List the calling account's active push subscriptions #
GET /api/v1/push/vapid-public-key Fetch the dispatcher's VAPID application-server public key #

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-push-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-push-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: UptimeMonitoring.com Push 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: Push
paths:
  /api/v1/push/subscribe:
    post:
      operationId: subscribeBrowserPush
      summary: Register a browser Web Push subscription
      description: 'Persists the browser''s `PushSubscription` object so the dispatcher

        can deliver notifications on monitor state transitions. The

        `p256dh` and `auth` fields are write-only secrets used server-side

        to encrypt push payloads — they are NEVER returned in the

        response. The 64 KB body limit and the global per-account

        200/min rate limiter both apply. Per-account cap is enforced

        atomically: an account holds **exactly 20** active subscriptions

        at steady state — concurrent subscribes never produce a 21st

        row. The 21st insert evicts the oldest by `created_at` (FIFO).

        The `endpoint` must be an `https://` URL with a public hostname;

        private/loopback/link-local/mDNS endpoints are rejected with

        `400 {"error":"endpoint must be HTTPS"}` (SSRF hardening).'
      tags:
      - Push
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PushSubscriptionRequest'
      responses:
        '201':
          description: Subscription stored.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PushSubscriptionResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '413':
          $ref: '#/components/responses/RequestEntityTooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedMediaType'
        '429':
          $ref: '#/components/responses/RateLimited'
  /api/v1/push/subscribe/{subscriptionID}:
    delete:
      operationId: unsubscribeBrowserPush
      summary: Revoke a browser Web Push subscription
      description: 'Removes the subscription if and only if it belongs to the calling

        account. A subscription that exists but belongs to another

        account is indistinguishable from one that does not exist —

        both return 404. This is intentional: the API does not leak

        cross-account row existence.'
      tags:
      - Push
      security:
      - bearerAuth: []
      parameters:
      - name: subscriptionID
        in: path
        required: true
        schema:
          type: integer
          format: int64
        description: Push subscription ID.
      responses:
        '204':
          description: Subscription deleted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          description: No subscription matched (or it belongs to another account).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/RateLimited'
  /api/v1/push/subscriptions:
    get:
      operationId: listBrowserPushSubscriptions
      summary: List the calling account's active push subscriptions
      description: 'Returns the calling account''s active push subscriptions newest

        first. The `p256dh` and `auth` secrets are NEVER included in

        the response. Returns `[]` (not `null`) when the account has

        no subscriptions.'
      tags:
      - Push
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Subscriptions list.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PushSubscriptionResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '429':
          $ref: '#/components/responses/RateLimited'
  /api/v1/push/vapid-public-key:
    get:
      operationId: getBrowserPushVapidPublicKey
      summary: Fetch the dispatcher's VAPID application-server public key
      description: 'Returns the base64url-encoded application-server public key the

        SPA must pass to `PushManager.subscribe({applicationServerKey})`

        before posting the resulting subscription to

        `POST /api/v1/push/subscribe`. The key is the public half of a

        VAPID keypair generated on the dispatcher''s first boot and

        persisted thereafter — not a secret, but auth-gated so the SPA

        already has a token by the time it asks. Returns 503 in the

        defensive case where the dispatcher router is up but the

        keypair has not been initialised yet (not reachable on the

        current boot order).'
      tags:
      - Push
      security:
      - bearerAuth: []
      responses:
        '200':
          description: VAPID public key.
          content:
            application/json:
              schema:
                type: object
                required:
                - public_key
                properties:
                  public_key:
                    type: string
                    description: 'Base64url-encoded (unpadded) uncompressed P-256

                      public key, ~87 characters, alphabet

                      `[-_A-Za-z0-9]`. Pass this directly as

                      `applicationServerKey` to

                      `PushManager.subscribe`.

                      '
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          description: VAPID keypair not yet initialised.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      required:
      - error
      properties:
        error:
          type: string
      example:
        error: something went wrong
    PushSubscriptionRequest:
      type: object
      required:
      - endpoint
      - p256dh
      - auth
      properties:
        endpoint:
          type: string
          format: uri
          description: 'Push service endpoint URL from the browser''s

            `PushSubscription`. Must be HTTPS with a non-empty host.

            '
          example: https://fcm.googleapis.com/fcm/send/abcd1234
        p256dh:
          type: string
          description: 'Base64url-encoded P-256 ECDH public key from the browser.

            Write-only — never returned in any response.

            '
        auth:
          type: string
          description: 'Base64url-encoded auth secret from the browser, used

            server-side to encrypt push payloads. Write-only —

            never returned in any response.

            '
        user_agent:
          type:
          - string
          - 'null'
          description: Optional client UA string for operator-facing UI.
    PushSubscriptionResponse:
      type: object
      properties:
        id:
          type: integer
          format: int64
        endpoint:
          type: string
          format: uri
        user_agent:
          type:
          - string
          - 'null'
        created_at:
          type: string
          format: date-time
      description: 'Persisted push subscription as exposed via the REST API. The

        `p256dh` and `auth` write-only secrets are intentionally

        omitted to prevent exfiltration via a compromised dashboard

        token.

        '
  responses:
    RateLimited:
      description: 'Per-account dispatcher rate limit exceeded (200 requests/minute).

        The `Retry-After` header gives the integer seconds until at least

        one token has refilled. The `X-RateLimit-*` trio reflects the

        bucket whose rejection produced this response — usually the global

        200/min cap; on `POST /api/v1/monitors` a 429 may instead reflect

        the per-route 20/min creation limit.

        '
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds until the next allowed request.
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: account rate limit exceeded; retry in 1s
    UnsupportedMediaType:
      description: 'The request `Content-Type` is not `application/json`. Write

        operations (POST, PUT, PATCH) require that header; a missing or

        non-JSON media type is rejected before the body is read.

        The `charset` parameter is accepted and ignored, so

        `application/json; charset=utf-8` is valid.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unsupported media type, expected application/json
    RequestEntityTooLarge:
      description: 'Request body exceeds the 64 KB hard limit. Per docs/SPEC.md

        §Hard Limits the dispatcher rejects any payload larger than

        65,536 bytes before it is decoded.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: request body exceeds 64 KB limit
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: invalid credentials
    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
    BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  headers:
    XRateLimitReset:
      schema:
        type: integer
      description: 'Unix epoch seconds at which the bucket would be full again if no

        further requests are made. Sub-second fragments are rounded up so

        `Reset - now` is never less than the actual refill duration.

        '
    XRateLimitLimit:
      schema:
        type: integer
      description: 'Bucket capacity for the limiter that produced this response. `200`

        for the global per-account dispatcher cap; `20` on a 429 from the

        per-route monitor-create limiter.

        '
    XRateLimitRemaining:
      schema:
        type: integer
      description: 'Tokens left in the bucket after this request was charged

        (floor of the post-charge token count). `0` on a 429 means the

        request was rejected with the bucket empty.

        '
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key (`umk_live_*`) or session token from OAuth exchange.

        '