# POST Data to an API
Source: https://docs.chain.link/chainlink-functions/tutorials/api-post-data

> For the complete documentation index, see [llms.txt](/llms.txt).

This tutorial shows you how to send a request to a Decentralized Oracle Network to call the [Countries information GraphQL API](https://trevorblades.github.io/countries/queries/continent). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the name, capital, and currency for the specified country to your smart contract. Because the endpoint is a GraphQL API, write a function that sends a GraphQL query in a [POST HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).

> **NOTE**
>
> Chainlink Functions is a self-service solution. You must ensure that the data sources or APIs specified in requests
> are of sufficient quality and have the proper availability for your use case. You are responsible for complying with
> the licensing agreements for all data providers that you connect with through Chainlink Functions. Violations of data
> provider licensing agreements or the [terms](https://chain.link/terms) can result in suspension or termination of your
> Chainlink Functions account.

> **NOTE: Maximum response size**
>
> You can return any number of responses as long as they are encoded in a `bytes` response. The maximum response size
> that you can return is 256 bytes.

> **CAUTION: Side effects**
>
> Building non-idempotent requests, such as sending an email or storing data on the cloud, is currently not recommended.
> An HTTP method is idempotent if the intended effect on the server when you make a single request is the same as the
> effect when you make several identical requests. Each oracle node runs the same computation in the [Offchain Reporting
> protocol](/architecture-overview/off-chain-reporting). If your Chainlink Function makes non-idempotent requests, it
> will cause redundant requests such as sending multiple emails or storing the same data multiple times.

## Tutorial

This tutorial is configured to get the country name, capital, and currency from [countries.trevorblades.com](https://countries.trevorblades.com/) in one request. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.

You can locate the scripts used in this tutorial in the [*examples/4-post-data* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/4-post-data).

To run the example:

1. Open the file `request.js`, which is located in the `4-post-data` folder.

2. Replace the consumer contract address and the subscription ID with your own values.

   ```javascript
   const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
   const subscriptionId = 3 // REPLACE this with your subscription ID
   ```

3. Make a request:

   ```shell
   node examples/4-post-data/request.js
   ```

   The script runs your function in a sandbox environment before making an onchain transaction:

   ```text
   $ node examples/4-post-data/request.js
   secp256k1 unavailable, reverting to browser version
   Start simulation...
   Simulation result {
     capturedTerminalOutput: 'Get name, capital and currency for country code: JP\n' +
       'HTTP POST Request to https://countries.trevorblades.com/\n' +
       'country response { country: { name: "Japan", capital: "Tokyo", currency: "JPY" } }\n',
     responseBytesHexstring: '0x7b226e616d65223a224a6170616e222c226361706974616c223a22546f6b796f222c2263757272656e6379223a224a5059227d'
   }
   ✅ Decoded response to string:  {"name":"Japan","capital":"Tokyo","currency":"JPY"}

   Estimate request costs...
   Fulfillment cost estimated to 1.007671833192655 LINK

   Make request...

   ✅ Functions request sent! Transaction hash 0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081. Waiting for a response...
   See your request in the explorer https://sepolia.etherscan.io/tx/0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081

   ✅ Request 0xc760ee5ca5c73999ca9c4ce426b9d2d44eab4429d3110276e57c445537ad5ddd successfully fulfilled. Cost is 0.257726519296170771 LINK.Complete response:  {
     requestId: '0xc760ee5ca5c73999ca9c4ce426b9d2d44eab4429d3110276e57c445537ad5ddd',
     subscriptionId: 2303,
     totalCostInJuels: 257726519296170771n,
     responseBytesHexstring: '0x7b226e616d65223a224a6170616e222c226361706974616c223a22546f6b796f222c2263757272656e6379223a224a5059227d',
     errorString: '',
     returnDataBytesHexstring: '0x',
     fulfillmentCode: 0
   }

   ✅ Decoded response to string:  {"name":"Japan","capital":"Tokyo","currency":"JPY"}
   ```

   The output of the example gives you the following information:

   - Your request is first run on a sandbox environment to ensure it is correctly configured.
   - The fulfillment costs are estimated before making the request.
   - Your request was successfully sent to Chainlink Functions. The transaction in this example is [0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081](https://sepolia.etherscan.io/tx/0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081) and the request ID is `0xc760ee5ca5c73999ca9c4ce426b9d2d44eab4429d3110276e57c445537ad5ddd`.
   - The DON successfully fulfilled your request. The total cost was: `0.257726519296170771 LINK`.
   - The consumer contract received a response in `bytes` with a value of `0x7b226e616d65223a224a6170616e222c226361706974616c223a22546f6b796f222c2263757272656e6379223a224a5059227d`. Decoding it offchain to `string` gives you a result:

     `{"name":"Japan","capital":"Tokyo","currency":"JPY"}`.

## Examine the code

### FunctionsConsumerExample.sol

### JavaScript example

#### source.js

The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/4-post-data/source.js). The code is self-explanatory and has comments to help you understand all the steps.

This JavaScript source code uses [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) to make HTTP requests. To request the `JP` country information, the source code calls the `https://countries.trevorblades.com/` URL and provides the query data in the HTTP request body. If you read the [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) documentation, you see that you must provide the following parameters:

- url: `https://countries.trevorblades.com/`
- data (HTTP body):

  ```
  {
      query: `{\
          country(code: "${countryCode}") { \
          name \
          capital \
          currency \
          } \
      }`,
  }
  ```

To check the expected API response:

- In your browser, open the countries GraphQL playground: `https://countries.trevorblades.com/`

- Write this query:

  ```
  {
  country(code: "JP") {
      name
      capital
      currency
  }
  }
  ```

- Click on *play* to get the answer :

  ```json
  {
    "data": {
      "country": {
        "name": "Japan",
        "capital": "Tokyo",
        "currency": "JPY"
      }
    }
  }
  ```

The main steps of the scripts are:

- Fetch the `countryCode` from `args`.

- Construct the HTTP object `countryRequest` using `Functions.makeHttpRequest`.

- Run the HTTP request.

- Read the country name, capital, and currency from the response.

- Construct a JSON object:

  ```javascript
  const result = {
    name: countryData.country.name,
    capital: countryData.country.capital,
    currency: countryData.country.currency,
  }
  ```

- Convert the JSON object to a JSON string using `JSON.stringify(result)`. This step is mandatory before encoding `string` to `bytes`.

- Return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the `Functions.string` helper function. **Note**: Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.

#### request.js

This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/4-post-data/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.

The script imports:

- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/4-post-data/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).

The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:

```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```

The primary function that the script executes is `makeRequestSepolia`. This function consists of five main parts:

1. Definition of necessary identifiers:
   - `routerAddress`: Chainlink Functions router address on Sepolia.
   - `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
   - `explorerUrl`: Block explorer URL of the Sepolia testnet.
   - `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
   - `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["JP"]`, which fetches country data for Japan.
   - `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
   - Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.

2. Simulating your request in a local sandbox environment:
   - Use `simulateScript` from the Chainlink Functions NPM package.
   - Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.string` in this example).

3. Estimating the costs:
   - Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost`.
   - The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.

4. Making a Chainlink Functions request:
   - Initialize your functions consumer contract using the contract address, abi, and ethers signer.
   - Call the `sendRequest` function of your consumer contract.

5. Waiting for the response:
   - Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
   - Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.string` in this example).