{"openapi":"3.1.0","info":{"title":"Nodary over Airnode","version":"1.0.0","description":"Nodary's aggregated price feeds, from one of the providers powering API3's data feeds. Crypto, stablecoin, liquid staking and forex pairs, each aggregated from multiple sources into one latest value.\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-nodary.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":"latestFeeds","type":"object","required":["operation","parameters"],"additionalProperties":false,"properties":{"operation":{"const":"latestFeeds","description":"The latest value of every feed Nodary serves, keyed by feed name."},"parameters":{"type":"object","additionalProperties":false,"required":[],"properties":{"name":{"description":"Feed names to limit to, comma separated. Omitted, every feed is returned.","type":"string","examples":["ETH/USD","BTC/USD"]}}},"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":"0xE70f1e8b22a21e4Bb5188918a3033341b281E4c0","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-nodary.fly.dev/api","routes":{"latestFeeds":{"method":"GET","path":"/feed/latest","parameters":{"name":"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"}}}