{"openapi":"3.1.0","info":{"title":"ETHBEAT CROPS API","version":"1.0.0","description":"CROPS is ETHBEAT's review of a protocol along four crops: censorship resistance, open source, privacy and security. Each crop gets a sentiment (good, warning, bad or neutral) and a status saying how far the review went. A protocol is listed in the CROPS guide (`inGarden`) when no crop is bad and it has an ossification score. Security is capped by that score: below 80 it is at most warning, and below 50, which means a critical change within roughly the last five weeks, it is bad. Separately, the set of reviewed protocols is attested onchain with the Ethereum Attestation Service.\n\nEvery response is a static file generated from the ETHBEAT repository, so it is served from a CDN with no API key and no rate limit.\n\n## Not found means not reviewed\n\n`/v1/project/{id}.json` and `/v1/address/{chainId}/{address}.json` answer 404 with an empty body when ETHBEAT has not reviewed the project or the address. Treat 404 as \"not reviewed\", not as an error.\n\n## Address lookups\n\nAddress files are keyed by EIP-155 chain id and lowercase address. Lowercase the address before you build the URL. A contract, a proxy implementation behind it, and a permission holder such as a governance multisig all resolve to the protocol. A shared contract lists every protocol that claims it, each once, with the name that protocol gives it.\n\n## Attestations are on ethereum\n\nThe attestation lives on ethereum (chain id 1). It proves the set ETHBEAT named, not that the ratings are attested: ratings change as protocols change and are served here without a transaction.\n\n## Verifying the set onchain\n\n1. Read the attestation from the EAS contract with the uid in `attestations.current`: `getAttestation(uid)`.\n2. Check `attester` and `schema` against `attestations.attester` and `attestations.schemaUid`, so an attestation someone else made cannot be mistaken for ETHBEAT's.\n3. Check it is the current one. The newest wins: of the attester's attestations under the schema that are not revoked, the one with the highest revision names the current set. A change is a new attestation that points to the one it supersedes through `refUID`; older ones stay valid in EAS but no longer count.\n4. Decode `projectIds`: these are the protocols ETHBEAT has reviewed, as of `reviewedAt`, at revision `revision`.\n5. For the rating per property, the reasoning and what was not looked at, read `/v1/project/{id}.json`."},"paths":{"/v1/address/{chainId}/{address}.json":{"get":{"summary":"Which protocol is this address?","description":"The reviewed protocols a contract, proxy implementation or permission holder belongs to, with a rating per property. A shared contract lists every protocol that claims it, each once, with the name that protocol gives it.","parameters":[{"name":"chainId","in":"path","required":true,"description":"EIP-155 chain id, e.g. 1 for Ethereum.","schema":{"type":"integer"}},{"name":"address","in":"path","required":true,"description":"Lowercase 0x-prefixed address.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResponse"}}}},"404":{"description":"The address is not part of any reviewed protocol."}}}},"/v1/project/{id}.json":{"get":{"summary":"Everything about one protocol","description":"The CROPS evaluations of one protocol, with the reasoning behind each rating.","parameters":[{"name":"id","in":"path","required":true,"description":"The project id or its slug.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"ETHBEAT has not reviewed this project."}}}},"/v1/crops.json":{"get":{"summary":"All reviewed protocols","description":"Every reviewed protocol in one response, with the full CROPS evaluations and the attestation that names them.","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CropsResponse"}}}}}}}},"components":{"schemas":{"AttestationsMeta":{"type":"object","properties":{"network":{"type":"string","description":"EAS network the attestation lives on."},"chainId":{"type":"number"},"eas":{"type":"string","description":"EAS contract address."},"schemaUid":{"type":"string"},"schema":{"type":"string","description":"EAS schema definition string."},"attester":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The attester Safe, or null until it is set."},"current":{"anyOf":[{"type":"object","properties":{"uid":{"type":"string"},"revision":{"type":"number"},"reviewedAt":{"type":"number","description":"Unix seconds."},"projectIds":{"type":"array","items":{"type":"string"},"description":"Sorted."},"txHash":{"type":"string"},"explorerUrl":{"type":"string"}},"additionalProperties":false,"required":["uid","revision","reviewedAt","projectIds","txHash","explorerUrl"]},{"type":"null"}],"description":"The attester's current attestation, which names the reviewed set, or null before it has attested."}},"additionalProperties":false,"required":["network","chainId","eas","schemaUid","schema","attester","current"]},"CropEvaluation":{"type":"object","properties":{"sentiment":{"enum":["good","warning","bad","neutral"]},"status":{"enum":["reviewed","partiallyReviewed","notReviewed","fullyTransparent"]},"license":{"type":"object","properties":{"spdxId":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"categories":{"type":"array","items":{"type":"string"},"description":"The OSI's own filing, e.g. 'superseded'."}},"additionalProperties":false,"required":["spdxId","name","url","categories"],"description":"Only on the open source crop, once the license is confirmed."},"points":{"type":"array","items":{"type":"string"}},"missing":{"type":"array","items":{"type":"string"}},"additionalConsiderations":{"type":"array","items":{"type":"string"}},"notReviewed":{"type":"array","items":{"type":"string"}}},"additionalProperties":false,"required":["sentiment","status","points","missing","additionalConsiderations","notReviewed"]},"Crops":{"type":"object","properties":{"censorshipResistance":{"$ref":"#/components/schemas/CropEvaluation"},"openSource":{"$ref":"#/components/schemas/CropEvaluation"},"privacy":{"$ref":"#/components/schemas/CropEvaluation"},"security":{"$ref":"#/components/schemas/CropEvaluation"}},"additionalProperties":false,"required":["censorshipResistance","openSource","privacy","security"]},"CropsSummary":{"type":"object","properties":{"censorshipResistance":{"type":"object","properties":{"sentiment":{"enum":["good","warning","bad","neutral"]},"status":{"enum":["reviewed","partiallyReviewed","notReviewed","fullyTransparent"]}},"additionalProperties":false,"required":["sentiment","status"]},"openSource":{"type":"object","properties":{"sentiment":{"enum":["good","warning","bad","neutral"]},"status":{"enum":["reviewed","partiallyReviewed","notReviewed","fullyTransparent"]}},"additionalProperties":false,"required":["sentiment","status"]},"privacy":{"type":"object","properties":{"sentiment":{"enum":["good","warning","bad","neutral"]},"status":{"enum":["reviewed","partiallyReviewed","notReviewed","fullyTransparent"]}},"additionalProperties":false,"required":["sentiment","status"]},"security":{"type":"object","properties":{"sentiment":{"enum":["good","warning","bad","neutral"]},"status":{"enum":["reviewed","partiallyReviewed","notReviewed","fullyTransparent"]}},"additionalProperties":false,"required":["sentiment","status"]}},"additionalProperties":false,"required":["censorshipResistance","openSource","privacy","security"]},"Attestation":{"type":"object","properties":{"uid":{"type":"string"},"revision":{"type":"number"},"reviewedAt":{"type":"number","description":"Unix seconds."},"explorerUrl":{"type":"string"}},"additionalProperties":false,"required":["uid","revision","reviewedAt","explorerUrl"]},"Project":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The ETHBEAT project page, or null when there is none."},"crops":{"$ref":"#/components/schemas/Crops"},"inGarden":{"type":"boolean","description":"False while any crop is bad or the project has no ossification score yet, even though it is reviewed."},"attestation":{"anyOf":[{"$ref":"#/components/schemas/Attestation"},{"type":"null"}],"description":"The onchain attestation naming this project, or null when it is not in the attested set. One attestation names the whole set, so it is the same for every attested project."}},"additionalProperties":false,"required":["id","slug","name","href","crops","inGarden","attestation"]},"CropsResponse":{"type":"object","properties":{"attestations":{"$ref":"#/components/schemas/AttestationsMeta"},"generatedAt":{"type":"number","description":"Unix seconds."},"commit":{"type":"string","description":"The l2beat/l2beat commit the data came from."},"projects":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}},"additionalProperties":false,"required":["attestations","generatedAt","commit","projects"]},"ProjectResponse":{"type":"object","properties":{"attestations":{"$ref":"#/components/schemas/AttestationsMeta"},"generatedAt":{"type":"number","description":"Unix seconds."},"commit":{"type":"string","description":"The l2beat/l2beat commit the data came from."},"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The ETHBEAT project page, or null when there is none."},"crops":{"$ref":"#/components/schemas/Crops"},"inGarden":{"type":"boolean","description":"False while any crop is bad or the project has no ossification score yet, even though it is reviewed."},"attestation":{"anyOf":[{"$ref":"#/components/schemas/Attestation"},{"type":"null"}],"description":"The onchain attestation naming this project, or null when it is not in the attested set. One attestation names the whole set, so it is the same for every attested project."}},"additionalProperties":false,"required":["attestations","generatedAt","commit","id","slug","name","href","crops","inGarden","attestation"]},"AddressMatch":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"href":{"anyOf":[{"type":"string"},{"type":"null"}]},"contractName":{"type":"string","description":"The contract or permission the address was matched as."},"crops":{"$ref":"#/components/schemas/CropsSummary"},"attestation":{"anyOf":[{"type":"object","properties":{"uid":{"type":"string"},"revision":{"type":"number"}},"additionalProperties":false,"required":["uid","revision"]},{"type":"null"}]}},"additionalProperties":false,"required":["id","slug","name","href","contractName","crops","attestation"]},"AddressResponse":{"type":"object","properties":{"attestations":{"$ref":"#/components/schemas/AttestationsMeta"},"generatedAt":{"type":"number","description":"Unix seconds."},"commit":{"type":"string","description":"The l2beat/l2beat commit the data came from."},"chainId":{"type":"number"},"address":{"type":"string","description":"Lowercase."},"matches":{"type":"array","items":{"$ref":"#/components/schemas/AddressMatch"},"description":"Every reviewed project that claims the address."}},"additionalProperties":false,"required":["attestations","generatedAt","commit","chainId","address","matches"]}}}}