You can get data through an oracle that calls an API, as blockchains themselves can't call APIs
Here is how to get data through a decentralized price feed. You can see a list of contract addresses and their price pair in the chainlink price feeds documentation.
pragma solidity ^0.6.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/interfaces/AggregatorInterface.sol";
contract ReferenceConsumer {
AggregatorInterface internal ref;
// For ETH-USD on ropsten, input the address:
// 0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507
constructor(address _aggregator) public {
ref = AggregatorInterface(_aggregator);
}
function getLatestAnswer() public view returns (int256) {
return ref.latestAnswer();
}
}
A more thorough explanation and example of using Chainlink Price Feeds can be found on the Chainlink blog.
As @crissi mentioned, you can use an oracle like Chainlink or Oraclize to call an external API. Using it from one source means that it also has a single source of failure for your smart contract, so ideally, you'd pull from a decentralized node service. See Chainlink again for more information here.
Decentralized Price Feed
Another simpler method you could use that doesn't call an external API would be to use a Chainlink Reference Contract. All you need to do is get the address of the aggregator contract. For ETH-USD on ropsten, that address is 0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507
. You can find a list of supported mainnet addresses here and testnet/mainnet addresses here.
These reference contracts are updated by a decentralized set of nodes to get the most recent price, without having the same single point of failure a centralized node has.
If you want to create your own group of centralized nodes to get the price, you can pull chainlink nodes as well with.
You can also pull from centralized nodes in Chainlink, but ideally you'd pull from a node network.
See this blog post for more information on external data collection.
Disclosure, I am the author of this blog post