{
    "openapi": "3.1.0",
    "info": {
        "title": "BugRater API",
        "version": "1.0.0",
        "summary": "Bug bounty programs rated by researchers, with platform metrics, scope and attack surface data.",
        "description": "Agents should prefer the MCP server at https://bugrater.com/mcp. Documentation: https://bugrater.com/docs. Terms: https://bugrater.com/terms.",
        "termsOfService": "https://bugrater.com/terms",
        "contact": {
            "name": "BugRater",
            "url": "https://bugrater.com/docs",
            "email": "hello@bugrater.com"
        }
    },
    "servers": [
        {
            "url": "https://bugrater.com"
        }
    ],
    "tags": [
        {
            "name": "MCP server",
            "description": "The easiest way in for an agent. Streamable HTTP, protocol versions 2025-03-26 through 2026-07-28, no account needed for public data. Setup for each client: https://bugrater.com/agents. The tools are listed in full in https://bugrater.com/llms-full.txt."
        },
        {
            "name": "Open lookups",
            "description": "Small public checks that need no credentials at all."
        },
        {
            "name": "Directory API",
            "description": "Programs, grades and reviews as JSON. Self-serve: create an agent token at https://bugrater.com/settings/agents and send it as a bearer token. 60 requests a minute."
        },
        {
            "name": "Attack Surface API",
            "description": "Enumerated subdomains, HTTP probes and exposure signals per program, priced per call. Pay with an Attack Surface subscription key (https://bugrater.com/attack-surface). Paying per call with x402 is switched off for now, so every call needs a key. Full field lists: https://bugrater.com/attack-surface/api-docs."
        },
        {
            "name": "Sign-in for MCP clients",
            "description": "OAuth 2.1 as the MCP authorization spec profiles it: dynamic client registration, public clients, PKCE S256. Clients discover all of it from the 401 on /mcp/account."
        }
    ],
    "paths": {
        "/mcp": {
            "post": {
                "tags": [
                    "MCP server"
                ],
                "summary": "MCP endpoint. Public tools without a token; member tools with one.",
                "operationId": "postMcp",
                "description": "JSON-RPC 2.0. Anonymous callers get 40 tool calls a minute per address, token holders 120.",
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": [
                    {},
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/mcp/account": {
            "post": {
                "tags": [
                    "MCP server"
                ],
                "summary": "The same server for a signed-in member. Without a token it answers 401 with OAuth metadata, so clients offer sign-in.",
                "operationId": "postMcpAccount",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/cve/{cve}": {
            "get": {
                "tags": [
                    "Open lookups"
                ],
                "summary": "Is this CVE in the named program's own published advisories?",
                "operationId": "getCveCve",
                "parameters": [
                    {
                        "name": "cve",
                        "in": "path",
                        "required": true,
                        "description": "e.g. CVE-2026-12345",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "program",
                        "in": "query",
                        "required": true,
                        "description": "Program slug to check the CVE against.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "verdict: matched, mismatch (credited to another vendor), unknown, or malformed; vendors: Vendors BugRater has it credited to; release: The advisory, when matched"
                    }
                },
                "security": []
            }
        },
        "/api/v1/researcher-credits": {
            "get": {
                "tags": [
                    "Open lookups"
                ],
                "summary": "Every published vendor-advisory credit for a researcher name.",
                "operationId": "getResearcherCredits",
                "parameters": [
                    {
                        "name": "name",
                        "in": "query",
                        "required": true,
                        "description": "The name as advisories credit it.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "total: credits, cves, vendors, first and latest date; byVendor: Per-vendor counts; cves: Up to 30 most recent CVEs; profile: The BugRater member, when the name is a verified claim"
                    }
                },
                "security": []
            }
        },
        "/api/v1/verify/{token}": {
            "get": {
                "tags": [
                    "Open lookups"
                ],
                "summary": "Verify a BugBadge attestation attached to a report.",
                "operationId": "getVerifyToken",
                "parameters": [
                    {
                        "name": "token",
                        "in": "path",
                        "required": true,
                        "description": "The 40-character attestation token.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "status: valid, expired, revoked or badge_revoked; researcher: username, profile and badge links; snapshot: The track record at minting time; minted_for: The program it was minted for; check it is yours; distinct_verifiers: How widely the token has travelled"
                    }
                },
                "security": []
            }
        },
        "/api/v1/keys/{username}": {
            "get": {
                "tags": [
                    "Open lookups"
                ],
                "summary": "A member's published end-to-end public key (P-256 JWK) and fingerprint, to encrypt collab content to them.",
                "operationId": "getKeysUsername",
                "parameters": [
                    {
                        "name": "username",
                        "in": "path",
                        "required": true,
                        "description": "BugRater username.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": []
            }
        },
        "/api/v1/programs": {
            "get": {
                "tags": [
                    "Directory API"
                ],
                "summary": "Every program, best graded first.",
                "operationId": "getPrograms",
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Rows to return, 1 to 100. Default 50.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "required": false,
                        "description": "Rows to skip. Default 0.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "data[]: slug, name, company, platform, type, bounty_low, bounty_high, grade, score, reviews, url; total, has_more: For paging"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/programs/{slug}": {
            "get": {
                "tags": [
                    "Directory API"
                ],
                "summary": "One program with its review metrics, reported practices and up to 100 reviews.",
                "operationId": "getProgramsSlug",
                "parameters": [
                    {
                        "name": "slug",
                        "in": "path",
                        "required": true,
                        "description": "Program slug, as in /programs/{slug}.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "data.metrics: would_submit_again_pct, would_recommend_pct, avg_skill, median_first_response, sentiment; data.reported_practices: Practice flag counts; data.reviews[]: Review text, ratings, outcomes; anonymous authors are null"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/rankings": {
            "get": {
                "tags": [
                    "Directory API"
                ],
                "summary": "Graded programs ranked on one board.",
                "operationId": "getRankings",
                "parameters": [
                    {
                        "name": "board",
                        "in": "query",
                        "required": false,
                        "description": "graded (default), triage, payers or cves.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Rows to return, 1 to 100. Default 50.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "required": false,
                        "description": "Rows to skip. Default 0.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/stats": {
            "get": {
                "tags": [
                    "Directory API"
                ],
                "summary": "Site-wide totals and the grade distribution.",
                "operationId": "getStats",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/reviews/{id}": {
            "get": {
                "tags": [
                    "Directory API"
                ],
                "summary": "One approved review.",
                "operationId": "getReviewsId",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Review id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/surface/programs": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "The board: every rated program with its rating, surge and crowd read.",
                "operationId": "getSurfacePrograms",
                "parameters": [
                    {
                        "name": "sort",
                        "in": "query",
                        "required": false,
                        "description": "score (default), surge, velocity or hunters.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Default 1.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Default 50.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.50 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.5
            }
        },
        "/api/v1/surface/movers": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "What is heating up, and what is under-hunted while still active.",
                "operationId": "getSurfaceMovers",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.50 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.5
            }
        },
        "/api/v1/surface/signals": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "The freshest high-value signals across every program.",
                "operationId": "getSurfaceSignals",
                "parameters": [
                    {
                        "name": "type",
                        "in": "query",
                        "required": false,
                        "description": "A signal type, e.g. staging_env, exposed_config, login_page or admin_panel. An unknown type is a free 400 that lists the valid ones.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "severity",
                        "in": "query",
                        "required": false,
                        "description": "info, low, medium or high.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Default 1.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Default 50.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.50 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.5
            }
        },
        "/api/v1/surface/programs/{id}": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "One program: rating and drivers, market read, enumeration depth.",
                "operationId": "getSurfaceProgramsId",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Attack Surface program id, from /api/v1/surface/programs.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.75 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.75
            }
        },
        "/api/v1/surface/programs/{id}/subdomains": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "Enumerated subdomains with DNS, liveness and attached signals.",
                "operationId": "getSurfaceProgramsIdSubdomains",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Attack Surface program id, from /api/v1/surface/programs.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $1.00 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 1
            }
        },
        "/api/v1/surface/programs/{id}/probes": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "HTTP probes: status, title, server, tech fingerprint, TLS issuer.",
                "operationId": "getSurfaceProgramsIdProbes",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Attack Surface program id, from /api/v1/surface/programs.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.50 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.5
            }
        },
        "/api/v1/surface/programs/{id}/signals": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "Exposure signals on one program, highest severity first.",
                "operationId": "getSurfaceProgramsIdSignals",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Attack Surface program id, from /api/v1/surface/programs.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.75 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.75
            }
        },
        "/api/v1/surface/programs/{id}/velocity": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "Daily intake series.",
                "operationId": "getSurfaceProgramsIdVelocity",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Attack Surface program id, from /api/v1/surface/programs.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "days",
                        "in": "query",
                        "required": false,
                        "description": "Window, default 90.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $0.50 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 0.5
            }
        },
        "/api/v1/surface/programs/{id}/full": {
            "get": {
                "tags": [
                    "Attack Surface API"
                ],
                "summary": "Everything for one program in a single call.",
                "operationId": "getSurfaceProgramsIdFull",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "Attack Surface program id, from /api/v1/surface/programs.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "description": "Missing or invalid credentials."
                    },
                    "429": {
                        "description": "Rate limited; see Retry-After."
                    },
                    "402": {
                        "description": "Payment required: $2.00 per call. The PAYMENT-REQUIRED header carries the x402 v2 offer; the body carries the v1 offer."
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "x-price-usd": 2
            }
        },
        "/.well-known/oauth-protected-resource": {
            "get": {
                "tags": [
                    "Sign-in for MCP clients"
                ],
                "summary": "Protected resource metadata (RFC 9728). Also at /mcp and /mcp/account suffixes.",
                "operationId": "getWellKnownOauthProtectedResource",
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": []
            }
        },
        "/.well-known/oauth-authorization-server": {
            "get": {
                "tags": [
                    "Sign-in for MCP clients"
                ],
                "summary": "Authorization server metadata (RFC 8414).",
                "operationId": "getWellKnownOauthAuthorizationServer",
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": []
            }
        },
        "/agents/oauth/register": {
            "post": {
                "tags": [
                    "Sign-in for MCP clients"
                ],
                "summary": "Dynamic client registration (RFC 7591). Public clients only.",
                "operationId": "postAgentsOauthRegister",
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": []
            }
        },
        "/agents/oauth/authorize": {
            "get": {
                "tags": [
                    "Sign-in for MCP clients"
                ],
                "summary": "Authorization endpoint. The member signs in and consents.",
                "operationId": "getAgentsOauthAuthorize",
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": []
            }
        },
        "/agents/oauth/token": {
            "post": {
                "tags": [
                    "Sign-in for MCP clients"
                ],
                "summary": "Code exchange with code_verifier. Returns a 90-day bearer token.",
                "operationId": "postAgentsOauthToken",
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                },
                "security": []
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Authorization: Bearer <token>. A personal agent token (bra_live_\u2026) from /settings/agents, or an API key."
            },
            "apiKey": {
                "type": "apiKey",
                "in": "header",
                "name": "X-API-Key",
                "description": "Attack Surface subscription key (bsk_live_\u2026)."
            },
            "x402": {
                "type": "apiKey",
                "in": "header",
                "name": "PAYMENT-SIGNATURE",
                "description": "x402 payment (https://x402.org). Send no credentials to get the 402 offer, then retry with the signed payment. v1 clients may use X-PAYMENT."
            }
        }
    },
    "externalDocs": {
        "url": "https://bugrater.com/docs",
        "description": "Reference and guides"
    }
}