# Using User-hosted Secrets in Requests
Source: https://docs.chain.link/chainlink-functions/tutorials/api-use-secrets-offchain

> 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 [Coinmarketcap API](https://coinmarketcap.com/api/documentation/v1/). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the `BTC/USD` asset price to your smart contract. Because the API requires you to provide an API key, this guide will also show you how to encrypt, sign your API key, and share the encrypted secret offchain with a Decentralized Oracle Network (DON).

The encrypted secrets are never stored onchain. This tutorial uses the threshold decryption feature. This tutorial shows you how to share encrypted secrets offchain with a Decentralized Oracle Network (DON) using a storage platform such as AWS S3, Google Drive, IPFS, or any other service where the DON can fetch secrets via HTTP. Read the [Secrets Management page](/chainlink-functions/resources/secrets) to learn more.

Read the [Using User-hosted (gist) Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets-gist) tutorial before you follow the steps in this example. This tutorial uses the same example but with a slightly different process:

1. Instead of relying on storing the encrypted secrets on gist, you will host your encrypted secrets on AWS S3.
2. Include the encrypted secrets in an `offchain-secrets.json` file.
3. Host the secrets file offchain (AWS S3).
4. Encrypt the S3 HTTPs URL .
5. Include the encrypted URL in your Chainlink Functions request.

> **CAUTION**
>
> Chainlink Functions is still in BETA. The use of secrets in your requests is an experimental feature that may not
> operate as expected and is subject to change. Use of this feature is at your own risk and may result in unexpected
> errors, possible revealing of the secret as new versions are released, or other issues.

> **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.

## Tutorial

This tutorial is configured to get the `BTC/USD` price with a request that requires API keys. 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/7-use-secrets-url* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/7-use-secrets-url).

1. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/).

2. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.

   ```shell
   npx env-enc set
   ```

3. Prepare the store for your encrypted secrets file.
   1. Create a [AWS free tier account](https://aws.amazon.com/free/).
   2. Follow [these steps](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html) to create a AWS S3 bucket. Choose a name for your bucket, set *ACLs enabled*, and turn off *Block all public access*.

### Build Offchain Secrets

Before you make a request, prepare the secrets file and host it offchain:

1. Encrypt the secrets and store them in the `offchain-secrets.json` file using the `gen-offchain-secrets` script of the `7-use-secrets-url` folder.

   ```bash
   node examples/7-use-secrets-url/gen-offchain-secrets.js
   ```

   Example:

   ```text
   $ node examples/7-use-secrets-url/gen-offchain-secrets.js
   secp256k1 unavailable, reverting to browser version
   Encrypted secrets object written to /functions-examples/offchain-secrets.json
   ```

2. Follow these [steps](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-an-object-bucket.html) to upload the file `offchain-secrets.json` to your AWS S3 bucket.

3. To make the file publicly accessible without authentication:
   1. Find the file in the bucket list, and click on it to open the object overview.
   2. Click on the *Permissions* tab to display the *Access control list (ACL)*.
   3. Click on *Edit*.
   4. Set *Everyone (public access)* Objects read, then confirm. This action makes the object readable by anyone on the internet.
   5. Note the object URL.
   6. To verify that the URL is publicly readable without authentication, open a new browser tab and copy/paste the object URL in the browser location bar. After you hit *Enter* , the browser will display the content of your encrypted secrets file.

4. Note the URL. You will need it in the following section. For example: `https://clfunctions.s3.eu-north-1.amazonaws.com/offchain-secrets.json`.

### Send a Request

To run the example:

1. Open the file `request.js`, which is located in the `7-use-secrets-url` 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. Replace the `secretsUrls` with your AWS S3 URL:

   ```javascript
   const secretsUrls = ["https://clfunctions.s3.eu-north-1.amazonaws.com/offchain-secrets.json"] // REPLACE WITH YOUR VALUES after running gen-offchain-secrets.js and uploading offchain-secrets.json to a public URL
   ```

4. Make a request:

   ```shell
   node examples/7-use-secrets-url/request.js
   ```

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

   ```text
   $ node examples/7-use-secrets-url/request.js
   secp256k1 unavailable, reverting to browser version
   Encrypted secrets object written to /Users/crystalgomes/smart-contract-examples/functions-examples/offchain-secrets.json
   crystalgomes@MB-CY16VK6DPG functions-examples % node examples/7-use-secrets-url/request.js

   secp256k1 unavailable, reverting to browser version
   Start simulation...
   Simulation result {
   capturedTerminalOutput: 'Price: 68196.20 USD\n',
   responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000680f24'
   }
   ✅ Decoded response to uint256:  6819620n

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

   Make request...

   Encrypt the URLs..

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

   ✅ Request 0xb308ca293859dab47d8848578291e687a0d9373274d1451a9c9667dc4bba5fca successfully fulfilled. Cost is 0.260029208488139025 LINK.Complete response:  {
   requestId: '0xb308ca293859dab47d8848578291e687a0d9373274d1451a9c9667dc4bba5fca',
   subscriptionId: 2303,
   totalCostInJuels: 260029208488139025n,
   responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000068146a',
   errorString: '',
   returnDataBytesHexstring: '0x',
   fulfillmentCode: 0
   }

   ✅ Decoded response to uint256:  6820970n
   ```

   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.

   - The AWS S3 URL is encrypted before sending it in the request.

   - Your request was successfully sent to Chainlink Functions. The transaction in this example is [0xadc0db0ddea7b9836b86a9c9e008bc97d47e5f92b0dcec9694d3944d0065c789](https://sepolia.etherscan.io/tx/0xadc0db0ddea7b9836b86a9c9e008bc97d47e5f92b0dcec9694d3944d0065c789) and the request ID is `0xb308ca293859dab47d8848578291e687a0d9373274d1451a9c9667dc4bba5fca`.

   - The DON successfully fulfilled your request. The total cost was: `0.260029208488139025 LINK`.

   - The consumer contract received a response in `bytes` with a value of `0x000000000000000000000000000000000000000000000000000000000068146a`. Decoding it offchain to `uint256` gives you a result: `6820970`.

## Examine the code

### FunctionsConsumerExample.sol

### JavaScript example

#### source.js

The JavaScript code is similar to the [Using Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets) tutorial.

#### gen-offchain-secrets.js

This explanation focuses on the [gen-offchain-secrets.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/7-use-secrets-url/gen-offchain-secrets.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 encrypts your secrets. After encryption, the script saves the encrypted secrets on a local file, `offchain-secrets.json`. You can then upload the file to your storage of choice (AWS S3 in this example).

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/7-use-secrets-url/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.

The primary function that the script executes is `generateOffchainSecretsFile`. This function can be broken into three 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.
   - `secrets`: The secrets object.
   - Initialization of ethers `signer` and `provider` objects. The Chainlink NPM package uses the signer to sign the encrypted secrets with your private key.

2. Encrypt the secrets:
   - Initialize a `SecretsManager` instance from the Chainlink Functions NPM package.
   - Call the `encryptSecrets` function from the created instance to encrypt the secrets.

3. Use the `fs` library to store the encrypted secrets on a local file, `offchain-secrets.json`.

#### request.js

This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/7-use-secrets-url/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/7-use-secrets-url/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 can be broken into six 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 `["1", "USD"]`, which fetches the BTC/USD price.
   - `secrets`: The secrets object. **Note**: Because we are sharing the URL of the encrypted secrets with the DON, the `secrets` object is only used during simulation.
   - `secretsUrls`: The URL of the encrypted secrets object.
   - `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.uint256` in this example).

3. Estimating the costs:
   - Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost` function.
   - 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. Encrypt the secrets, then create a gist containing the encrypted secrets object. This is done in two steps:
   - Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
   - Call the `encryptedSecretsUrls` function of the `SecretsManager` instance. This function encrypts the secrets URL. **Note**: The encrypted URL will be sent to the DON when making a request.

5. 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.

6. 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.uint256` in this example).