# Multi-Variable Responses
Source: https://docs.chain.link/any-api/get-request/examples/multi-variable-responses


<AnyApiCallout callout="usefunctions" />

This guide explains how to make an HTTP GET request to an external API from a smart contract, using Chainlink's [Request & Receive Data](/any-api/introduction) cycle and then receive multiple responses.
This is known as **multi-variable** or **multi-word** responses.

## Example

This example shows how to:

- Fetch several responses in one single call.

[Cryptocompare GET /data/price/ API](https://min-api.cryptocompare.com/documentation?key=Price\&cat=SingleSymbolPriceEndpoint) returns the current price of any cryptocurrency in any other currency that you need. To check the response, you can directly paste the following URL in your browser `https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=BTC` or run this command in your terminal:

```bash
curl -X 'GET' \
  'https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=BTC' \
  -H 'accept: application/json'
```

The response should be similar to the following:

```json
{
  "BTC": 0.07297
}
```

The request above shows how to get the price of *ETH* against *BTC*. Now let say we want the price of *ETH* against several currencies: *BTC*, *USD*, and *EUR*. Our contract will have to support receiving multiple responses.
To consume an API with multiple responses, your contract should inherit from [ChainlinkClient](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/ChainlinkClient.sol). This contract exposes a struct called `Chainlink.Request`, which your contract should use to build the API request. The request should include the following parameters:

- Link token address
- Oracle address
- Job id
- Request fee
- Task parameters
- Callback function signature

> **CAUTION: Note on Funding Contracts**
>
> Making a GET request will fail unless your deployed contract has enough LINK to pay for it. **Learn how to [Acquire testnet LINK](/resources/acquire-link) and [Fund your contract](/resources/fund-your-contract)**.

Assume that a user wants to obtain the ETH price quoted against three different currencies: *BTC* , *USD* and *EUR*. If they use only a single-word job, it would require three different requests. For a comparison, see the [Single Word Response](/any-api/get-request/examples/single-word-response) example. To make these requests more efficient, use multi-word responses to do it all in a single request as shown in the following example:

```sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import {Chainlink, ChainlinkClient} from "@chainlink/contracts/src/v0.8/operatorforwarder/ChainlinkClient.sol";
import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol";

/**
 * Request testnet LINK and ETH here: https://faucets.chain.link/
 * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here:
 * https://docs.chain.link/docs/link-token-contracts/
 */

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */
contract MultiWordConsumer is ChainlinkClient, ConfirmedOwner {
  using Chainlink for Chainlink.Request;

  bytes32 private jobId;
  uint256 private fee;

  // multiple params returned in a single oracle response
  uint256 public btc;
  uint256 public usd;
  uint256 public eur;

  event RequestMultipleFulfilled(bytes32 indexed requestId, uint256 btc, uint256 usd, uint256 eur);

  /**
   * @notice Initialize the link token and target oracle
   * @dev The oracle address must be an Operator contract for multiword response
   *
   *
   * Sepolia Testnet details:
   * Link Token: 0x779877A7B0D9E8603169DdbD7836e478b4624789
   * Oracle: 0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD (Chainlink DevRel)
   * jobId: 53f9755920cd451a8fe46f5087468395
   *
   */
  constructor() ConfirmedOwner(msg.sender) {
    _setChainlinkToken(0x779877A7B0D9E8603169DdbD7836e478b4624789);
    _setChainlinkOracle(0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD);
    jobId = "53f9755920cd451a8fe46f5087468395";
    fee = (1 * LINK_DIVISIBILITY) / 10; // 0,1 * 10**18 (Varies by network and job)
  }

  /**
   * @notice Request multiple parameters from the oracle in a single transaction
   */
  function requestMultipleParameters() public {
    Chainlink.Request memory req = _buildChainlinkRequest(jobId, address(this), this.fulfillMultipleParameters.selector);
    req._add("urlBTC", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=BTC");
    req._add("pathBTC", "BTC");
    req._add("urlUSD", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
    req._add("pathUSD", "USD");
    req._add("urlEUR", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=EUR");
    req._add("pathEUR", "EUR");
    _sendChainlinkRequest(req, fee); // MWR API.
  }

  /**
   * @notice Fulfillment function for multiple parameters in a single request
   * @dev This is called by the oracle. recordChainlinkFulfillment must be used.
   */
  function fulfillMultipleParameters(
    bytes32 requestId,
    uint256 btcResponse,
    uint256 usdResponse,
    uint256 eurResponse
  ) public recordChainlinkFulfillment(requestId) {
    emit RequestMultipleFulfilled(requestId, btcResponse, usdResponse, eurResponse);
    btc = btcResponse;
    usd = usdResponse;
    eur = eurResponse;
  }

  /**
   * Allow withdraw of Link tokens from the contract
   */
  function withdrawLink() public onlyOwner {
    LinkTokenInterface link = LinkTokenInterface(_chainlinkTokenAddress());
    require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
  }
}
```

To use this contract:

1. [Open the contract in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/APIRequests/MultiWordConsumer.sol).

2. Compile and deploy the contract using the Injected Provider environment. The contract includes all the configuration variables for the *Sepolia* testnet. Make sure your wallet is set to use *Sepolia*. The *constructor* sets the following parameters:
   - The Chainlink Token address for *Sepolia* by calling the [`setChainlinkToken`](/any-api/api-reference/#setchainlinktoken) function.
   - The Oracle contract address for *Sepolia* by calling the [`setChainlinkOracle`](/any-api/api-reference/#setchainlinkoracle) function.
   - The `jobId`: A specific job for the oracle node to run. In this case, you must call a job that is specifically configured to return *ETH* price against *BTC*, *USD* and *EUR*. You can find the job spec for the Chainlink node [here](/chainlink-nodes/job-specs/multi-word-job).

3. Fund your contract with 0.1 LINK. To learn how to send LINK to contracts, read the [Fund Your Contracts](/resources/fund-your-contract) page.

4. Call the `btc`, `usd` , and `eur` functions to confirm that the respective `btc`, `usd` , and `eur` state variables are equal to *zero*.

5. Run the `requestMultipleParameters` function. This builds the `Chainlink.Request` using the correct parameters:
   - The `req._add("urlBTC", "CRYPTOCOMPARE_ETH_BTC_URL")` request parameter provides the oracle node with the [url](https://min-api.cryptocompare.com/data/price?fsym=ETH\&tsyms=BTC) where to fetch the *ETH-BTC* price. Same logic for `req._add("urlEUR", "CRYPTOCOMPARE_ETH_BTC_URL")` and `req._add("urlUSD", "CRYPTOCOMPARE_ETH_BTC_URL")`.
   - THe `req._add('pathBTC', 'BTC')` request parameter tells the oracle node where to fetch the *ETH-BTC* price in the *json* response. Same logic for `req._add('pathUSD', 'EUR')` and `req._add('pathEUR', 'USD')`.
     Because you provide the URLs and paths, the `MultiWordConsumer` in the example can call any public API as long as the URLs and paths are correct.

6. After few seconds, call the `btc`, `usd` , and `eur` functions. You should get a non-zero responses.
   The job spec for the Chainlink node in this example can be found [here](/chainlink-nodes/job-specs/multi-word-job).