{
  "x402Version": 2,
  "items": [
    {
      "resource": "https://dappgrade.vercel.app/v1/score",
      "type": "http",
      "method": "GET",
      "x402Version": 2,
      "description": "dappgrade score — pre-transaction health/safety verdict for an onchain app, by contract address. Returns ok / caution / avoid / unknown with the coverage the verdict rests on.",
      "mimeType": "application/json",
      "serviceName": "dappgrade",
      "tags": [
        "defi",
        "security",
        "risk",
        "onchain",
        "dapp",
        "pre-transaction"
      ],
      "accepts": [
        {
          "scheme": "exact",
          "network": "eip155:8453",
          "amount": "10000",
          "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "payTo": "0x4a0aed4ce878e44ef922941f2b06137bc0b69b69",
          "maxTimeoutSeconds": 120,
          "extra": {
            "name": "USD Coin",
            "version": "2"
          }
        }
      ],
      "extensions": {
        "bazaar": {
          "info": {
            "input": {
              "type": "http",
              "queryParams": {
                "chain": "8453",
                "address": "0x6cb442acf35158d5eda88fe602221b67b400be3e"
              },
              "method": "GET"
            },
            "output": {
              "type": "json",
              "example": {
                "verdict": "caution",
                "verdict_reason": "coverage 65% < 80%; tier-0 static checks cannot clear a dApp (§2.3)",
                "reasons": [
                  {
                    "code": "COVERAGE_BELOW_TARGET",
                    "detail": "coverage 65% < 80%"
                  },
                  {
                    "code": "TIER_0_ONLY",
                    "detail": "tier-0 static checks cannot clear a dApp (§2.3)"
                  },
                  {
                    "code": "CHECK_FAILED",
                    "check": "trust.headers",
                    "detail": "present: HSTS"
                  }
                ],
                "score": 87,
                "coverage": 0.65,
                "tier": 0,
                "flags": [],
                "freshness": {
                  "checked_at": "2026-08-17T09:47:12Z",
                  "age_seconds": 25140,
                  "stale": false
                }
              }
            }
          },
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "input": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "const": "http"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "GET"
                    ]
                  },
                  "queryParams": {
                    "type": "object",
                    "properties": {
                      "chain": {
                        "type": "string",
                        "description": "EVM chain — id (8453), CAIP-2 (eip155:8453), or name (base, mainnet, arbitrum, optimism)"
                      },
                      "address": {
                        "type": "string",
                        "pattern": "^0x[a-fA-F0-9]{40}$",
                        "description": "the contract address the agent is about to call"
                      }
                    },
                    "required": [
                      "chain",
                      "address"
                    ]
                  }
                },
                "required": [
                  "type",
                  "method"
                ],
                "additionalProperties": false
              },
              "output": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string"
                  },
                  "example": {
                    "type": "object",
                    "properties": {
                      "verdict": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "caution",
                          "avoid",
                          "unknown"
                        ],
                        "description": "decision-shaped: ok = proceed, caution = hold, avoid = abort, unknown = not rated (never read as safe)"
                      },
                      "verdict_reason": {
                        "type": "string",
                        "description": "prose; wording not stable — branch on reasons[].code"
                      },
                      "reasons": {
                        "type": "array",
                        "description": "stable machine-readable causes behind the verdict; see /v1/methodology → reason_codes",
                        "items": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string"
                            },
                            "detail": {
                              "type": "string"
                            },
                            "check": {
                              "type": "string",
                              "description": "on CHECK_FAILED"
                            },
                            "flag": {
                              "type": "string",
                              "description": "on CRITICAL_FLAG"
                            }
                          }
                        }
                      },
                      "score": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "coverage": {
                        "type": "number",
                        "description": "0..1 fraction of the rubric that actually ran; meaningless to read score without it"
                      },
                      "tier": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "flags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "freshness": {
                        "type": [
                          "object",
                          "null"
                        ],
                        "description": "checked_at/age_seconds/stale. Pass max_age=<seconds> to get `unknown` + STALE_FOR_CALLER instead of an old answer — the observation still travels, so that response is billed normally. The scored fields are absent entirely (not null) on an `unknown` where we have no answer, and that one is free."
                      }
                    }
                  }
                },
                "required": [
                  "type"
                ]
              }
            },
            "required": [
              "input"
            ]
          }
        }
      }
    }
  ]
}