{
 "$schema": "https://agentdrives.com/schemas/tool.schema.json",
 "id": "prd_01m5w11sgx7wdt95egkqr47dcb",
 "ids": {
  "org": "org_01m5w11sgxxhv1rmfhjacyh93d",
  "surfaces": {
   "web": "srf_01m5w11sgx8xg0nnqk200mjg64",
   "api": "srf_01m5w11sgxn4c3myqx8qps8end",
   "mcp": "srf_01m5w11sgxfd1w14ar5tzd3p0s",
   "cli": "srf_01m5w11sgxgrcj6e22r9wdag0h"
  },
  "slugs": [
   "gotify"
  ],
  "domain": "gotify.net"
 },
 "slug": "gotify",
 "name": "Gotify",
 "url": "https://gotify.net",
 "domain": "gotify.net",
 "category": "push-notifications",
 "category_name": "Push notifications",
 "tested_at": "2026-10-26",
 "run": "20261026T110354Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261026T110354Z",
   "date": "2026-10-26",
   "level": 5,
   "engine": {
    "model": "claude-opus-5-5",
    "driver": 5,
    "signed": true,
    "inbox": null,
    "robots": "skip",
    "version": "2026.10.26",
    "commit": "5fcdb911f0dcc3c91a9794ca76f8d4896244f439",
    "prompts": {
     "version": "2026.10.26",
     "commit": "9bef5e75f8e732d063fdfff8e766feca445cb123"
    },
    "rules": {
     "version": "2026.10.26",
     "commit": "5fcdb911f0dcc3c91a9794ca76f8d4896244f439"
    }
   },
   "stop": null,
   "paid": false,
   "agent_paid": null
  }
 ],
 "level": 5,
 "level_name": "Autonomous",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 1,
  "tries": 1,
  "self_start": true
 },
 "badges": [
  "agent-can-leave"
 ],
 "not_counted": null,
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: runs locally",
   "way": "local"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 83% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "na",
   "text": "No plan to buy",
   "value": "nothing",
   "route": "none"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes what it made",
   "how": "no-account",
   "left": "removed",
   "delete": {
    "state": "yes",
    "text": "Deletes what it made",
    "why": null
   }
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Learn",
   "state": "yes",
   "text": "Docs it can act on: an OpenAPI and an MCP server",
   "have": [
    "openapi",
    "mcp"
   ],
   "docs": "gaps"
  },
  {
   "key": "access",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: runs locally",
   "way": "local",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 83% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "na",
   "text": "No plan to buy",
   "value": "nothing",
   "route": "none",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes what it made",
   "how": "no-account",
   "left": "removed",
   "delete": {
    "state": "yes",
    "text": "Deletes what it made",
    "why": null
   },
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "local",
   "label": "Runs locally",
   "routes": [
    "local"
   ],
   "minutes": 3,
   "core": "5/6"
  }
 ],
 "minutes": 3,
 "next": {
  "to": null,
  "text": "Does it all on its own; there is nothing to pay"
 },
 "stop": null,
 "core": "5/6",
 "scores": {
  "coverage": 90,
  "reliability": 100,
  "resilience": 65,
  "setup": 80,
  "surface_coverage": 98,
  "docs_accuracy": 89,
  "docs_completeness": 85
 },
 "parts": {
  "holds_up": 82,
  "docs_match": 88,
  "setup": 80,
  "security": "private",
  "standards": [
   {
    "standard": "MCP discovery",
    "state": "current",
    "behind": null,
    "value": "ok"
   },
   {
    "standard": "OpenAPI",
    "state": "behind",
    "behind": 3,
    "value": "2.0"
   }
  ]
 },
 "reliability_method": "pass^k",
 "resilience": {
  "parts": {
   "error_legibility": 95,
   "recovery": 100,
   "idempotency": 0
  },
  "summary": {
   "error_legibility": "clear",
   "recovery": "good",
   "idempotency": "risky",
   "rate_limits": "none-seen",
   "notes": "Errors name the missing field or the missing object and suggest the fix for elevation; repeated creates duplicate (no Idempotency-Key support) and no rate limit was seen in 15 calls."
  }
 },
 "stress": [
  {
   "capability": "Send a push message via REST API",
   "probe": "message field missing",
   "outcome": "400 {\"error\":\"Bad Request\",\"errorCode\":400,\"errorDescription\":\"Field 'message' is required\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Set message priority to control notification behavior",
   "probe": "priority as a string",
   "outcome": "400 {\"error\":\"Bad Request\",\"errorCode\":400,\"errorDescription\":\"json: cannot unmarshal string into Go struct field CreateMessage.priority of type int\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "List or delete messages",
   "probe": "delete a message id that does not exist",
   "outcome": "404 {\"error\":\"Not Found\",\"errorCode\":404,\"errorDescription\":\"message does not exist\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Create an application (a sender)",
   "probe": "application without name",
   "outcome": "400 {\"error\":\"Bad Request\",\"errorCode\":400,\"errorDescription\":\"Field 'name' is required\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Send a push message via REST API",
   "probe": "same create sent twice with an Idempotency-Key",
   "outcome": "200 ids 12 and 13: duplicate",
   "grade": "clear",
   "idempotent": "no",
   "rate_limit": null
  },
  {
   "capability": "Create an application (a sender)",
   "probe": "same app create twice",
   "outcome": "200 ids 7 and 8: two apps with the same name",
   "grade": "clear",
   "idempotent": "no",
   "rate_limit": null
  },
  {
   "capability": "List or delete messages",
   "probe": "burst of 15 GET /message?limit=1",
   "outcome": "200 all statuses [200], no RateLimit/Retry-After headers",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": "none-seen"
  },
  {
   "capability": "List or delete messages",
   "probe": "wrong client token",
   "outcome": "401 {\"error\":\"Unauthorized\",\"errorCode\":401,\"errorDescription\":\"cannot parse token: private key must be 32 bytes\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Send a push message via REST API",
   "probe": "wrong app token",
   "outcome": "401 {\"error\":\"Unauthorized\",\"errorCode\":401,\"errorDescription\":\"cannot parse token: private key must be 32 bytes\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Set message priority to control notification behavior",
   "probe": "priority out of the documented range (1000)",
   "outcome": "200 {\"id\":14,\"appid\":1,\"message\":\"prio range\",\"title\":\"agentdrives-prio\",\"priority\":1000,\"date\":\"26 Oct 2026\"}",
   "grade": "silent",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Subscribe to the message stream over WebSocket",
   "probe": "open /stream with a wrong token",
   "outcome": "HTTP/1.1 401 Unauthorized son\nDate: Mon, 26 Oct 2026 11:22:39 GMT\nContent-Length: 139\n\n{\"error\":\"Unauthorized\",\"errorCode\":401,\"errorDescription\":\"cannot parse token: base64 decode failed: illegal bas",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "Create an application (a sender)",
   "probe": "delete an app that still has messages, then use its token",
   "outcome": "401 messages of the app left: 0; old token -> 401 {\"error\":\"Unauthorized\",\"errorCode\":401,\"errorDescription\":\"you need to provide a valid access token or user credentials",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  },
  {
   "capability": "List or delete messages",
   "probe": "revoked client token",
   "outcome": "401 {\"error\":\"Unauthorized\",\"errorCode\":401,\"errorDescription\":\"you need to provide a valid access token or user credentials to access this api\"}",
   "grade": "clear",
   "idempotent": null,
   "rate_limit": null
  }
 ],
 "surface_audit": {
  "totals": {
   "items": 60,
   "documented": 55,
   "safe": 55,
   "exercised": 55,
   "passed": 54,
   "skipped": 0,
   "blocked": 0,
   "not_run": 0,
   "match": 49,
   "drift": 6,
   "broken_doc": 0,
   "docs_complete": 39,
   "docs_partial": 15,
   "docs_missing": 1,
   "errors_clear": 10,
   "errors_vague": 0,
   "errors_silent": 0
  }
 },
 "coverage_core": 83,
 "coverage_own": 83,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 5,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": false
 },
 "methodology": 42,
 "rules_date": "2026-10-30",
 "engine": {
  "model": "claude-opus-5-5",
  "driver": 5,
  "signed": true,
  "inbox": null,
  "robots": "skip",
  "version": "2026.10.26",
  "commit": "5fcdb911f0dcc3c91a9794ca76f8d4896244f439",
  "prompts": {
   "version": "2026.10.26",
   "commit": "9bef5e75f8e732d063fdfff8e766feca445cb123"
  },
  "rules": {
   "version": "2026.10.26",
   "commit": "5fcdb911f0dcc3c91a9794ca76f8d4896244f439"
  }
 },
 "same_level_drives": 1,
 "drives": 1,
 "same_stop_drives": 1,
 "works_assisted": null,
 "freshness": "fresh",
 "newer_drives": null,
 "nothing_to_pay": true,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": null,
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "home",
   "at": "2026-10-26"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "verified",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "gotify.net/docs (27 pages) and Swagger at /api-docs (spec.json, Swagger 2.0); no llms.txt, no Markdown pages."
  },
  "signup": {
   "status": "headless",
   "note": "Self-hosted only, no hosted sign-up. The release binary creates the admin from GOTIFY_DEFAULTUSER_PASS; our own user was registered with POST /user (GOTIFY_REGISTRATION=true).",
   "way": "local"
  },
  "verify": {
   "status": "n/a",
   "note": "No email verification in Gotify."
  },
  "credentials": {
   "status": "headless",
   "note": "POST /client (basic auth) returned a client token once; POST /application returned an app token once.",
   "via": ""
  },
  "first_call": {
   "status": "headless",
   "note": "GET /current/user with X-Gotify-Key returned 200.",
   "route": "account"
  },
  "first_action": {
   "status": "headless",
   "note": "POST /application created an app, listed by GET /application."
  },
  "pay": {
   "status": "n/a",
   "grade": "n/a",
   "rails": [],
   "rail_ids": [],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "none",
   "route": "none",
   "checkout": {
    "reached": "no",
    "processor": "none",
    "captcha": "none",
    "three_ds": "not_seen",
    "card_form": false,
    "phone_field": "none",
    "wallets": [],
    "rail_offer": "none",
    "price": null,
    "currency": null,
    "period": null,
    "plan": null,
    "last_button": null
   },
   "person": "none",
   "ours": "none",
   "note": "Free MIT software: no pricing page, checkout or 402 anywhere; we paid nothing."
  },
  "cancel": {
   "status": "n/a",
   "grade": "n/a",
   "note": "Nothing to cancel: there is nothing to pay for.",
   "docs_note": "Nothing to cancel: Gotify has no paid plans.",
   "nothing": "nothing_to_pay"
  },
  "delete": {
   "status": "headless",
   "note": "DELETE /user/2 as admin returned 200, and that user's password then got 401; the last admin can't be deleted ('cannot delete last admin'), so the instance and its data were removed.",
   "left": "removed",
   "after_hours": null,
   "account": false
  }
 },
 "routes": [
  {
   "route": "local",
   "offered": "documented",
   "tried": true,
   "not_tried": null,
   "result": "in",
   "wall": null,
   "person": "none",
   "brings": "nothing",
   "fresh": true,
   "minutes": 3,
   "browser": false
  }
 ],
 "checkout": {
  "reached": "no",
  "rail_offer": "none"
 },
 "docs": {
  "at": "2026-10-26",
  "read": 27,
  "listed": 27,
  "sampled": false,
  "overall": "gaps",
  "getting_started": "found",
  "auth": "found",
  "errors": "found",
  "examples": "good",
  "freshness": "fresh",
  "newest": "2026-10-10",
  "core_pages": "2 of 6",
  "capabilities": "gaps",
  "label": "Some gaps"
 },
 "claims": {
  "claimed": 9,
  "tried": 9,
  "held": 7,
  "broken": 0,
  "unclear": 2,
  "not_tried": 0,
  "undocumented_works": 1
 },
 "pay_options": {
  "checked": "2026-10-26",
  "source": "probe",
  "options": [],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": null,
   "card_required": null,
   "free_plan": null
  },
  "owner_fixes": []
 },
 "surfaces": {
  "api": true,
  "cli": true,
  "sdk": false,
  "mcp": "official",
  "llms_txt": false,
  "webhooks": false,
  "sandbox": false
 },
 "urls": {
  "docs": "https://gotify.net/docs/",
  "llms_txt": null,
  "mcp": null
 },
 "surface_notes": {
  "api": "REST, 42 operations, self-hosted",
  "mcp": "official, 1 tool, unreleased (master image only)",
  "cli": "gotify-cli 2.4.0: push, watch, init, config"
 },
 "surface_sizes": [
  {
   "kind": "api",
   "listed": 42,
   "tested": 42
  },
  {
   "kind": "mcp",
   "listed": 3,
   "tested": 3
  },
  {
   "kind": "cli",
   "listed": 2,
   "tested": 2
  }
 ],
 "can_do": [
  "Install its own Gotify server without a browser from the release binary",
  "Create applications and clients and get their tokens through the API",
  "Push messages with priority, Markdown, click URL, big image and Android intent extras",
  "Receive new messages live over the /stream WebSocket",
  "Run the Android app's own receive calls (client login, /stream?token=, catch-up GET /message) and get every field it turns into a notification",
  "List, page and delete messages per app or all at once",
  "Rotate an application token",
  "Push from the official CLI with --url and --token",
  "Load a Go plugin and configure it over the API",
  "Map OIDC groups to admin rights",
  "Delete users and their data"
 ],
 "cannot_do": [
  {
   "what": "See a message arrive as an Android notification",
   "why": "The gotify/android app draws the notification on a phone. Every server call the app makes works without a browser (3 of 3), but no API, CLI or web route shows or reads the notification itself."
  },
  {
   "what": "Use the documented MCP endpoint on the current release",
   "why": "/mcp is not in v3.1.1 (404); it exists only on the master image."
  },
  {
   "what": "Run gotify init from a script",
   "why": "The CLI's init needs an interactive terminal."
  }
 ],
 "blockers": [],
 "tips_for_agents": [
  "Run the release binary with GOTIFY_SERVER_PORT and GOTIFY_DEFAULTUSER_PASS in gotify-server.env; port 80 needs root.",
  "Use HTTP Basic auth for deletes, user management, password change and token rotation; a client token gets 403 until POST /client/{id}/elevate.",
  "Store app and client tokens at creation: the API never shows them again (PUT responses carry a token that does not work).",
  "Push with POST /message and an app token; set extras.client::display.contentType=text/markdown for Markdown.",
  "Call gotify push with --url and --token (or $GOTIFY_TOKEN) instead of gotify init, which needs a TTY.",
  "For MCP, run gotify/server:master and send Authorization: Bearer <app token> to /mcp; its only tool is send_message.",
  "To act as a phone client, do what gotify/android does: POST /client with Basic auth, open /stream?token=<client token>, and after a reconnect page GET /message?limit=10 for ids newer than the last one seen."
 ],
 "selfhost": null,
 "edge_case": "self-host",
 "summary": "Gotify is self-hosted only, and an agent can install it without a browser in a minute and run the job through its REST API: create apps and clients, push messages with priority and Markdown, stream them live and delete them. Five of the six core tasks passed 3 of 3. The sixth, receiving a notification on Android, was only partly checked: the Android app's own receive calls all work without a browser, but the notification drawn on the phone is out of an agent's sight. The documented MCP endpoint is not in any release yet (v3.1.1 answers 404); on the master image it speaks MCP (the 28 Jul 2026 spec) with one send_message tool.",
 "wall": "",
 "plan_scope": "free (open source, self-hosted)",
 "robots_stop": null,
 "robots": null,
 "terms": null,
 "terms_read": null,
 "email_gate": null,
 "plain": {
  "summary": "Gotify is free push-notification software that you run on your own server. An agent installed it, made its own account and sent, streamed and deleted messages without help. It could not check the notification that appears on a phone.",
  "can_do": [
   "Install its own Gotify server in about a minute",
   "Create apps and receiver clients and get their keys",
   "Send messages with priority, Markdown, links and images",
   "Receive messages live as they are sent",
   "List and delete messages",
   "Send from the official command-line tool",
   "Load a plugin and set it up",
   "Delete the user and the server data"
  ],
  "cannot_do": [
   {
    "what": "See a message arrive as a phone notification",
    "why": "The notification is drawn by the Android app, which our agent couldn't see."
   },
   {
    "what": "Use the MCP endpoint on the latest release",
    "why": "The endpoint is only in the unreleased master image."
   },
   {
    "what": "Run the CLI setup command from a script",
    "why": "gotify init needs an interactive terminal."
   }
  ]
 },
 "plan_gated": [],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "capability": "Send a push message via REST API",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /message",
    "mcp": "send_message",
    "cli": "gotify push",
    "ui": null
   },
   "check": "GET /message or GET /application/{id}/message shows the new message",
   "capability_id": "cap_fhzmwqhe",
   "source": "https://gotify.net/docs/pushmsg",
   "result": "done",
   "via": "api",
   "done_on": [
    "api",
    "cli",
    "mcp"
   ]
  },
  {
   "id": "cap-02",
   "capability": "Create an application (a sender)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /application",
    "mcp": null,
    "cli": null,
    "ui": "Apps tab"
   },
   "check": "GET /application lists the new application with its token shown once",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/docs/pushmsg",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-03",
   "capability": "Subscribe to the message stream over WebSocket",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "GET /stream",
    "mcp": null,
    "cli": null,
    "ui": "WebUI live view"
   },
   "check": "WebSocket connection receives a JSON message frame as soon as POST /message is called",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/api-docs",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-04",
   "capability": "List or delete messages",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "GET /message, DELETE /message, DELETE /message/{id}, GET/DELETE /application/{id}/message",
    "mcp": null,
    "cli": null,
    "ui": "WebUI message list"
   },
   "check": "GET /message no longer returns the deleted message id",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/api-docs",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-05",
   "capability": "Receive push notifications on Android",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "gotify/android app"
   },
   "check": "Android app shows a system notification for a newly pushed message",
   "capability_id": "cap_fhzmwqhe",
   "source": "https://gotify.net/",
   "result": "partial",
   "via": "api"
  },
  {
   "id": "cap-06",
   "capability": "Set message priority to control notification behavior",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /message (priority field)",
    "mcp": "send_message (priority arg)",
    "cli": "gotify push -p",
    "ui": "application default-priority setting"
   },
   "check": "a message pushed with priority 8 triggers sound+vibration in gotify/android per the priority table",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/docs/priority",
   "result": "done",
   "via": "api",
   "done_on": [
    "api",
    "cli"
   ]
  },
  {
   "id": "cap-07",
   "capability": "Render a message as Markdown",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /message extras client::display.contentType",
    "mcp": "send_message (markdown arg)",
    "cli": null,
    "ui": null
   },
   "check": "GET /message shows extras.client::display.contentType = text/markdown and the WebUI renders it as formatted markdown",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/docs/msgextras",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-08",
   "capability": "Attach a click URL or big image to a notification",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /message extras client::notification",
    "mcp": "send_message (click_url, big_image_url args)",
    "cli": null,
    "ui": null
   },
   "check": "GET /message shows extras.client::notification.click.url or bigImageUrl set",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/docs/msgextras",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-09",
   "capability": "Upload or remove an application icon image",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /application/{id}/image, DELETE /application/{id}/image",
    "mcp": null,
    "cli": null,
    "ui": "Apps tab edit"
   },
   "check": "GET /application shows the application's image field changed",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/api-docs",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-10",
   "capability": "Create and manage clients (receivers)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET/POST /client, PUT/DELETE /client/{id}",
    "mcp": null,
    "cli": null,
    "ui": "Clients tab"
   },
   "check": "GET /client lists the new client with a token issued once",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/api-docs",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-11",
   "capability": "Elevate a session before a sensitive action",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /client/{id}/elevate",
    "mcp": null,
    "cli": null,
    "ui": "re-auth prompt"
   },
   "check": "a subsequent DELETE /client/{id} with the elevated token returns 200 instead of 403",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/docs/session-elevation",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-12",
   "capability": "Push a message with an attached image via Markdown",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /message (message body with markdown image syntax)",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "the message renders the linked image in the WebUI",
   "capability_id": "cap_394b5egs",
   "source": "https://gotify.net/docs/more-pushmsg",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-13",
   "capability": "Trigger an Android intent when a message is received",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /message extras android::action.onReceive.intentUrl",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "GET /message shows extras.android::action.onReceive.intentUrl set",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/docs/msgextras",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-14",
   "capability": "Install a plugin that sends messages or handles webhooks",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /plugin, POST /plugin/{id}/config",
    "mcp": null,
    "cli": null,
    "ui": "Plugins tab"
   },
   "check": "GET /plugin lists the plugin as enabled and its config reads back the submitted YAML",
   "capability_id": "cap_x4n6bnwy",
   "source": "https://gotify.net/docs/plugin",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-15",
   "capability": "Map OIDC identity-provider groups to admin/user permissions",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "config via GOTIFY_OIDC_GROUPS_* env vars"
   },
   "check": "a user in the configured admin group logs in via OIDC and GET /current/user shows admin permissions",
   "capability_id": "cap_bs3hvrpm",
   "source": "https://gotify.net/docs/oidc",
   "result": "done",
   "via": "browser",
   "done_on": [
    "browser"
   ]
  },
  {
   "id": "cap-16",
   "capability": "Manage users as an admin",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "GET/POST /user, GET/POST/DELETE /user/{id}",
    "mcp": null,
    "cli": null,
    "ui": "Users tab (admin)"
   },
   "check": "GET /user lists the newly created user",
   "capability_id": null,
   "unmapped": "own_feature",
   "source": "https://gotify.net/api-docs",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-17",
   "capability": "Change the current user's password",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "POST /current/user/password",
    "mcp": null,
    "cli": null,
    "ui": "account settings"
   },
   "check": "subsequent login succeeds only with the new password",
   "capability_id": null,
   "unmapped": "access_step",
   "source": "https://gotify.net/docs/session-elevation",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-18",
   "capability": "Self-register a new account when registration is enabled",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "POST /user (public registration, when GOTIFY_REGISTRATION=true)",
    "mcp": null,
    "cli": null,
    "ui": "registration form"
   },
   "check": "GET /user (admin) shows the self-registered account",
   "capability_id": null,
   "unmapped": "access_step",
   "source": "https://gotify.net/docs/config",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-19",
   "capability": "Check server health and version information",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "GET /gotifyinfo, GET /health, GET /version",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "GET /version returns the running server's version string",
   "capability_id": null,
   "unmapped": "not_a_job",
   "source": "https://gotify.net/api-docs",
   "result": "done",
   "via": "api",
   "done_on": [
    "api"
   ]
  },
  {
   "id": "cap-20",
   "capability": "Develop and load a custom Go plugin",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "GET /plugin lists the plugin loaded from GOTIFY_PLUGINSDIR after server restart",
   "capability_id": "cap_4qp39fpq",
   "source": "https://gotify.net/docs/plugin",
   "result": "done",
   "via": "cli",
   "done_on": [
    "cli"
   ]
  }
 ],
 "stale": false,
 "unreachable_since": null,
 "not_driven_since": null,
 "icon": "/logos/gotify.png",
 "agent_kinds": {
  "browser": {
   "who": "An assistant in a browser",
   "passed": [
    "signup",
    "first_action"
   ],
   "stop": null,
   "why": null,
   "tone": "pass",
   "text": "Signs up and does 83% of the core work, all on its own."
  },
  "direct": {
   "who": "An agent talking to it directly",
   "passed": [
    "signup",
    "credentials",
    "first_call",
    "first_action"
   ],
   "stop": null,
   "why": null,
   "tone": "pass",
   "text": "Signs up, gets an API key, makes its first API call and does 83% of the core work, all on its own."
  }
 },
 "sdk": {
  "packages": [],
  "read_at": "2026-11-01T21:10:46Z"
 },
 "surface_reach": null,
 "connect": {
  "docs": {
   "url": "https://gotify.net/docs/",
   "state": "tested"
  }
 },
 "surface_sources": {
  "docs": "https://gotify.net/docs/",
  "api": "https://gotify.net/api-docs",
  "mcp": "https://gotify.net/docs/mcp",
  "cli": "https://gotify.net/docs/pushmsg"
 },
 "copilot_connector": null,
 "stripe_directory": null,
 "in_stripe_directory": null,
 "stripe_projects": null,
 "pay_rails": [],
 "stop_evidence": null,
 "wall_vendor": null,
 "mcp_sign_in": null,
 "safety_issues": 0,
 "fix_counts": {
  "small": 8,
  "medium": 1,
  "large": 0,
  "total": 9
 },
 "evidence_sha256": "e47fa470072ce8c3aa7a330fd0f6a8ce9d084a5a88e2c5105404f72f7e2346cd",
 "first_seen": "2026-10-26",
 "license": {
  "name": "CC BY 4.0",
  "url": "https://creativecommons.org/licenses/by/4.0/"
 },
 "correction": {
  "status": "none",
  "open": 0,
  "since": null,
  "reply_by": null
 },
 "attribution": null,
 "confirmation": {
  "state": "awaiting",
  "drives": 1,
  "agree": 1,
  "review": null,
  "text": "1 drive, awaiting confirmation"
 },
 "stop_shot": null,
 "stop_shot_hash": null,
 "attempts_count": 98,
 "detail": {
  "public": false,
  "in": [
   "report",
   "api"
  ],
  "since": "2026-10-17"
 },
 "what_it_does": "Gotify is free push-notification software that you run on your own server.",
 "kind": "product",
 "rules_version": "rules-2026-10-30-42",
 "rules_url": "https://agentdrives.com/method/changelog#rules-2026-10-30-42",
 "category_median": null,
 "peers": {
  "API-03": {
   "basis": "all",
   "n": 88,
   "below": 0,
   "above": 53,
   "percentile": 20
  },
  "API-07": {
   "basis": "all",
   "n": 98,
   "below": 0,
   "above": 89,
   "percentile": 5
  },
  "DOCS-08": {
   "basis": "all",
   "n": 142,
   "below": 88,
   "above": 0,
   "percentile": 81
  },
  "DOCS-10": {
   "basis": "all",
   "n": 142,
   "below": 39,
   "above": 31,
   "percentile": 53
  },
  "DOCS-11": {
   "basis": "all",
   "n": 142,
   "below": 10,
   "above": 44,
   "percentile": 38
  },
  "IN-11": {
   "basis": "all",
   "n": 146,
   "below": 108,
   "above": 0,
   "percentile": 87
  },
  "IN-12": {
   "basis": "all",
   "n": 148,
   "below": 98,
   "above": 0,
   "percentile": 83
  },
  "LEAVE-03": {
   "basis": "all",
   "n": 145,
   "below": 56,
   "above": 28,
   "percentile": 60
  },
  "MCP-03": {
   "basis": "all",
   "n": 66,
   "below": 4,
   "above": 0,
   "percentile": 53
  },
  "MCP-04": {
   "basis": "all",
   "n": 66,
   "below": 0,
   "above": 46,
   "percentile": 15
  },
  "MCP-05": {
   "basis": "all",
   "n": 66,
   "below": 1,
   "above": 20,
   "percentile": 36
  },
  "MCP-06": {
   "basis": "all",
   "n": 66,
   "below": 50,
   "above": 0,
   "percentile": 88
  },
  "MCP-07": {
   "basis": "all",
   "n": 66,
   "below": 32,
   "above": 0,
   "percentile": 74
  },
  "MCP-11": {
   "basis": "all",
   "n": 66,
   "below": 33,
   "above": 0,
   "percentile": 75
  },
  "PAY-05": {
   "basis": "all",
   "n": 119,
   "below": 0,
   "above": 34,
   "percentile": 36
  },
  "PROTO-02": {
   "basis": "all",
   "n": 94,
   "below": 0,
   "above": 2,
   "percentile": 49
  }
 },
 "probe": {
  "checked": "2026-11-01",
  "status": "ok",
  "sign_up_page": "not-found",
  "wall": "none",
  "llms_txt": false,
  "mcp": "none",
  "openapi": false,
  "payment_402": null,
  "payment_rails": [],
  "files": {
   "openapi": {
    "url": null,
    "found": false
   },
   "llms_txt": {
    "url": null,
    "found": false
   },
   "llms_full": {
    "url": null,
    "found": false
   }
  }
 },
 "probe_history": [
  {
   "checked": "2026-11-01",
   "status": "ok",
   "sign_up_page": "not-found",
   "wall": "none",
   "llms_txt": false,
   "mcp": "none",
   "openapi": false,
   "payment_402": null,
   "payment_rails": []
  },
  {
   "checked": "2026-10-31",
   "status": "ok",
   "sign_up_page": "not-found",
   "wall": "none",
   "llms_txt": false,
   "mcp": "none",
   "openapi": false,
   "payment_402": null,
   "payment_rails": []
  },
  {
   "checked": "2026-10-30",
   "status": "ok",
   "sign_up_page": "error",
   "wall": "none",
   "llms_txt": false,
   "mcp": "none",
   "openapi": false,
   "payment_402": null,
   "payment_rails": []
  }
 ],
 "surface_changes": [],
 "agent_reports": null,
 "verdict": "L5 · Autonomous: our agent got in on its own, and no checkpoint stopped it. Gotify is self-hosted with no hosted sign-up, so our agent registered its own user with POST /user, then took a client token from POST /client and an app token from POST /application. GET /current/user returned 200, and the agent created and listed an app through the REST API. Pay and cancel read n/a: Gotify is free MIT software with no pricing page or checkout. DELETE /user as admin returned 200, and because the last admin can't be deleted, the instance and its data were removed. The documented MCP endpoint answered 404 on the release.",
 "changes": {
  "source": "store",
  "drives": [
   {
    "run": "20261026T110354Z",
    "date": "2026-10-26",
    "level": 5,
    "stop": null,
    "entry": "self-start",
    "driver": 5,
    "listed": true,
    "paid": false,
    "agent_paid": null
   }
  ],
  "events": [],
  "feed": "https://agentdrives.com/api/tools/gotify/changes.json"
 },
 "agreement": null,
 "method_release": "2026-Q4.27",
 "found": {
  "agent_blockers": 0,
  "surface_issues": 7
 },
 "agent_surfaces": {
  "api": {
   "state": "tested",
   "reachable": true,
   "documented": 42,
   "tested": 42,
   "source": "https://gotify.net/api-docs"
  },
  "mcp": {
   "state": "tested",
   "reachable": true,
   "documented": 3,
   "tested": 3,
   "source": "https://gotify.net/docs/mcp"
  },
  "cli": {
   "state": "tested",
   "reachable": true,
   "documented": 2,
   "tested": 2,
   "source": "https://gotify.net/docs/pushmsg"
  },
  "sdk": {
   "state": "none_found",
   "documented": null,
   "tested": null,
   "source": null
  },
  "docs": {
   "state": "tested",
   "documented": 27,
   "tested": 27,
   "source": "https://gotify.net/docs/"
  },
  "payment": {
   "state": "none_found",
   "documented": null,
   "tested": null,
   "source": null
  }
 },
 "issues_found": 7,
 "rank": 1,
 "rank_of": 1,
 "rank_change": null,
 "rank_since": "2026-10-29",
 "links": {
  "category": [
   {
    "label": "Communication APIs",
    "href": "https://agentdrives.com/categories/communication"
   },
   {
    "label": "Push notifications",
    "href": "https://agentdrives.com/categories/push-notifications"
   }
  ],
  "tasks": [
   {
    "label": "Set a member's role or permissions",
    "href": "https://agentdrives.com/tasks/set-a-member-s-role-or-permissions"
   },
   {
    "label": "Connect a third-party integration",
    "href": "https://agentdrives.com/tasks/connect-a-third-party-integration"
   },
   {
    "label": "Build an app, bot or plugin for the product",
    "href": "https://agentdrives.com/tasks/build-an-app-bot-or-plugin-for-the-product"
   },
   {
    "label": "Send an email with an attachment",
    "href": "https://agentdrives.com/tasks#send-an-email-with-an-attachment"
   }
  ],
  "walls": [],
  "vendors": [],
  "standards": [
   {
    "label": "MCP",
    "href": "https://agentdrives.com/standards/mcp",
    "note": "tools an agent can call"
   }
  ],
  "steps": [
   {
    "label": "Find",
    "href": "https://agentdrives.com/access/find"
   },
   {
    "label": "Get in",
    "href": "https://agentdrives.com/access/get-in"
   },
   {
    "label": "Use",
    "href": "https://agentdrives.com/access/use"
   },
   {
    "label": "Pay",
    "href": "https://agentdrives.com/access/pay"
   },
   {
    "label": "Leave",
    "href": "https://agentdrives.com/access/leave"
   }
  ],
  "rivals": [],
  "compare": [],
  "rail": [
   {
    "label": "Watch this product",
    "href": "https://agentdrives.com/watch"
   },
   {
    "label": "Get the data",
    "href": "https://agentdrives.com/data#plans"
   }
  ]
 },
 "capability_matrix": [
  {
   "id": "cap-01",
   "name": "Send a push message via REST API",
   "core": true,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "done",
    "cli": "done",
    "ui": "none"
   }
  },
  {
   "id": "cap-02",
   "name": "Create an application (a sender)",
   "core": true,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-03",
   "name": "Subscribe to the message stream over WebSocket",
   "core": true,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-04",
   "name": "List or delete messages",
   "core": true,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-05",
   "name": "Receive push notifications on Android",
   "core": true,
   "result": "partial",
   "surfaces": {
    "api": "partial",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-06",
   "name": "Set message priority to control notification behavior",
   "core": true,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "untried",
    "cli": "done",
    "ui": "untried"
   }
  },
  {
   "id": "cap-07",
   "name": "Render a message as Markdown",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "untried",
    "cli": "none",
    "ui": "none"
   }
  },
  {
   "id": "cap-08",
   "name": "Attach a click URL or big image to a notification",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "untried",
    "cli": "none",
    "ui": "none"
   }
  },
  {
   "id": "cap-09",
   "name": "Upload or remove an application icon image",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-10",
   "name": "Create and manage clients (receivers)",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-11",
   "name": "Elevate a session before a sensitive action",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-12",
   "name": "Push a message with an attached image via Markdown",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "none"
   }
  },
  {
   "id": "cap-13",
   "name": "Trigger an Android intent when a message is received",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "none"
   }
  },
  {
   "id": "cap-14",
   "name": "Install a plugin that sends messages or handles webhooks",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-15",
   "name": "Map OIDC identity-provider groups to admin/user permissions",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "none",
    "mcp": "none",
    "cli": "none",
    "ui": "done"
   }
  },
  {
   "id": "cap-16",
   "name": "Manage users as an admin",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-17",
   "name": "Change the current user's password",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-18",
   "name": "Self-register a new account when registration is enabled",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "untried"
   }
  },
  {
   "id": "cap-19",
   "name": "Check server health and version information",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "done",
    "mcp": "none",
    "cli": "none",
    "ui": "none"
   }
  },
  {
   "id": "cap-20",
   "name": "Develop and load a custom Go plugin",
   "core": false,
   "result": "done",
   "surfaces": {
    "api": "none",
    "mcp": "none",
    "cli": "done",
    "ui": "none"
   }
  }
 ],
 "category_place": {
  "category": "push-notifications",
  "products": 1,
  "higher": 0,
  "same_level": 0,
  "as_of": "2026-10-26",
  "stop": null,
  "rivals_by": "level",
  "rivals": []
 },
 "page": "https://agentdrives.com/tools/gotify?via=api"
}