{"openapi":"3.1.0","info":{"title":"Context7 over Airnode","version":"2.0.0","description":"Context7 indexes the documentation of software libraries, frameworks and APIs, and answers a question about one of them with the snippets that answer it: code examples and documentation passages, each with a link to the source it came from. Libraries are indexed per version, so an answer can be about the release a project actually uses rather than whatever is current.\n\nFind the library first with searchLibraries, which returns Context7's ID for it and the versions it has indexed, then ask getContext about that ID. searchDocumentation does both in one call when a library's name is enough.\n\nWhat comes back is documentation as Context7 indexed it, not instructions, and the scores on a library say how well it is indexed rather than whether it is safe to use.\n\nEvery response carries an EIP-191 signature from the Airnode that served it, so the data can be attributed back to its source rather than trusted on reputation."},"servers":[{"url":"https://airnode-context7.fly.dev"}],"paths":{"/":{"get":{"operationId":"getDocumentation","summary":"This document.","description":"Describes the operations this Airnode serves and how to verify what it returns. Free.","responses":{"200":{"description":"An OpenAPI document describing this Airnode.","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"operationId":"performRequest","summary":"Perform an operation and attest to the response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"searchLibraries","type":"object","required":["operation","parameters"],"additionalProperties":false,"properties":{"operation":{"const":"searchLibraries","description":"Find a library by name and get the Context7 ID and versions to ask getContext with.","x-airnode-returns":{"results":"array","searchFilterApplied":"boolean"}},"parameters":{"type":"object","additionalProperties":false,"required":["libraryName","query"],"properties":{"libraryName":{"description":"The library's name as a person would write it.","type":"string","minLength":1,"maxLength":500,"examples":["react","next.js","express"]},"query":{"description":"The question the library is wanted for. It ranks the candidates, so a name shared by several projects resolves to the one that answers it.","type":"string","minLength":1,"maxLength":500,"examples":["How to manage state with hooks"]},"fast":{"description":"true skips the model that reranks the results, which answers faster and ranks worse.","type":"boolean","default":false}}},"responseProjection":{"type":"object","additionalProperties":{"type":"string"},"description":"Optional. Maps a name of your choosing to an RFC 6901 JSON Pointer into the upstream response, such as {\"price\": \"/ethereum/usd\"}. data then carries those names instead of the whole body, and the projection is part of the signed request identity. A pointer the response does not have is a 400."}}},{"title":"getContext","type":"object","required":["operation","parameters"],"additionalProperties":false,"properties":{"operation":{"const":"getContext","description":"Answer a question about one library, or one release of it, with code examples and documentation passages.","x-airnode-returns":{"codeSnippets":"array","infoSnippets":"array","rules":"object"}},"parameters":{"type":"object","additionalProperties":false,"required":["libraryId","query"],"properties":{"libraryId":{"description":"Context7's ID for the library, from searchLibraries, optionally followed by a version it listed, with a slash or an @.","type":"string","minLength":1,"maxLength":500,"pattern":"^/[^/]+/[^/]+([/@][^/]+)?$","examples":["/reactjs/react.dev","/vercel/next.js","/vercel/next.js/v15.1.8"]},"query":{"description":"The question to answer from the library's documentation.","type":"string","minLength":1,"maxLength":500,"examples":["How to use useState?"]},"fast":{"description":"true skips the model that reranks the snippets, which answers faster and ranks worse.","type":"boolean","default":false}}},"responseProjection":{"type":"object","additionalProperties":{"type":"string"},"description":"Optional. Maps a name of your choosing to an RFC 6901 JSON Pointer into the upstream response, such as {\"price\": \"/ethereum/usd\"}. data then carries those names instead of the whole body, and the projection is part of the signed request identity. A pointer the response does not have is a 400."}}},{"title":"searchDocumentation","type":"object","required":["operation","parameters"],"additionalProperties":false,"properties":{"operation":{"const":"searchDocumentation","description":"Answer a question from the documentation of whichever libraries it is about, in one call.","x-airnode-returns":{"codeSnippets":"array","infoSnippets":"array","rules":"object","version":"object"}},"parameters":{"type":"object","additionalProperties":false,"required":["query"],"properties":{"query":{"description":"The question or task. Long questions and pasted error output are accepted.","type":"string","minLength":1,"maxLength":2000,"examples":["How do I write optimistic updates with TanStack Query v5?"]},"library":{"description":"The library to search, as a name such as next.js or as a Context7 ID such as /vercel/next.js. A version tag on an ID, as /vercel/next.js@15, works like version for that library. One library per call, and a comma-separated list is read as one name. To search several libraries at once, leave this out and name them in the query: Context7 picks up to four from it.","type":"string","minLength":1,"maxLength":120,"examples":["react","/vercel/next.js"]},"version":{"description":"The release the question is about. Context7 prefers documentation for that release and falls back to current documentation when it has none, which the version field of the answer reports per library. latest is the same as leaving it out.","type":"string","pattern":"^([Ll][Aa][Tt][Ee][Ss][Tt]|[Vv]?[0-9]+([._][0-9]+){0,2}([-+][a-zA-Z0-9.-]+)?)$","examples":["15.2","v5"]},"language":{"description":"A programming language to prefer. It ranks snippets in that language higher and excludes nothing.","type":"string","minLength":1,"maxLength":40,"examples":["TypeScript"]}}},"responseProjection":{"type":"object","additionalProperties":{"type":"string"},"description":"Optional. Maps a name of your choosing to an RFC 6901 JSON Pointer into the upstream response, such as {\"price\": \"/ethereum/usd\"}. data then carries those names instead of the whole body, and the projection is part of the signed request identity. A pointer the response does not have is a 400."}}}]}}}},"responses":{"200":{"description":"The upstream response and the attestation over it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Attestation"}}}},"400":{"description":"The operation exists but the parameters or the projection are missing, unknown or malformed, or the projection names a path the response does not have."},"404":{"description":"No such operation."},"502":{"description":"The upstream API could not be reached or refused the request."}}}}},"components":{"schemas":{"Attestation":{"type":"object","required":["airnode","requestHash","timestamp","data","signature"],"properties":{"airnode":{"type":"string","description":"The address whose signature attests to this response."},"requestHash":{"type":"string","description":"Identifies the request this response answers."},"timestamp":{"type":"string","description":"Unix seconds at which the response was signed."},"data":{"description":"The upstream response body: the JSON value when it parses as JSON, the text as received otherwise. With a projection, an object keyed by the names it asked for."},"signature":{"type":"string","description":"The attestation itself."}}}}},"x-airnode":{"address":"0x871B88D4261Fce8B5e6D195812437Fc33c6AB4f5","version":"0.1.2","attestation":{"scheme":"eip191-secp256k1","digest":"keccak256(abi.encodePacked(bytes32 requestHash, uint256 timestamp, bytes dataBytes))","dataBytes":"UTF-8 of data, or of its compact JSON when data is not a string","requestHash":"keccak256(utf8(JSON.stringify([operation, parameterEntriesSortedByName]))), where an object value is itself entries sorted by name, at any depth, and an array keeps its order. A request that carries a projection appends its entries, sorted the same way, as a third element","verify":"Recover the signer of the signature over the digest and check it equals the address above."},"passthrough":{"url":"https://airnode-context7.fly.dev/api","routes":{"searchLibraries":{"method":"GET","path":"/v2/libs/search","parameters":{"libraryName":"query","query":"query","fast":"query"}},"getContext":{"method":"GET","path":"/v2/context","query":{"type":"json"},"parameters":{"libraryId":"query","query":"query","fast":"query"}},"searchDocumentation":{"method":"GET","path":"/v3/search","query":{"type":"json"},"parameters":{"query":"query","library":"query","version":"query","language":"query"}}},"parameters":{"x-airnode-sign":"false skips the signature: no attestation headers, and the body streamed through with no size cap.","x-airnode-project":"alias:pointer, once per field to keep, each pointer an RFC 6901 JSON Pointer into the upstream response. The body becomes an object of those aliases, the signature covers it, and a pointer the response does not have is a 400."},"flow":"Send the request the provider documents, method, path, query and body as they are, to url followed by the route's path. The body comes back as the upstream sent it, with the upstream's status, and on success the attestation is in the X-Airnode-Address, X-Airnode-Request-Hash, X-Airnode-Timestamp and X-Airnode-Signature headers, with the operation served in X-Airnode-Operation. Every query parameter starting with x-airnode- is this Airnode's own, listed under parameters, and never reaches the upstream.","requestHash":"keccak256(utf8(JSON.stringify([\"passthrough\", method, path, queryEntriesSortedByName, body]))), where method is upper case, path and query are what was sent after url with the Airnode's own parameters removed, and body is the request body as sent, or an empty string. A request that carries a projection appends its entries, sorted by name, as a sixth element","dataBytes":"UTF-8 of the response body exactly as received, or of the projected object as compact JSON"}}}