# Step 3: Connecting to the API
We're now ready to start implementing the connector.
Over the course of this tutorial, we'll be editing a few files that were generated by the code generator:
- `source-exchange-rates-tutorial/source_exchange_rates_tutorial/spec.yaml`: This is the [spec file](../../connector-specification-reference.md). It describes the inputs used to configure the connector.
- `source-exchange-rates-tutorial/source_exchange_rates_tutorial/exchange_rates_tutorial.yaml`: This is the connector definition. It describes how the data should be read from the API source.
- `source-exchange_rates-tutorial/integration_tests/configured_catalog.json`: This is the connector's [catalog](../../../understanding-airbyte/beginners-guide-to-catalog.md). It describes what data is available in a source
- `source-exchange-rates-tutorial/integration_tests/sample_state.json`: This is a sample state object to be used to test [incremental syncs](../../cdk-python/incremental-stream.md).
We'll also be creating the following files:
- `source-exchange-rates-tutorial/secrets/config.json`: This is the configuration file we'll be using to test the connector. Its schema should match the schema defined in the spec file.
- `source-exchange-rates-tutorial/secrets/invalid_config.json`: This is an invalid configuration file we'll be using to test the connector. Its schema should match the schema defined in the spec file.
- `source_exchange_rates_tutorial/schemas/rates.json`: This is the [schema definition](../../cdk-python/schemas.md) for the stream we'll implement.
## Updating the connector spec and config
Let's populate the specification (`spec.yaml`) and the configuration (`secrets/config.json`) so the connector can access the access key and base currency.
1. We'll add these properties to the connector spec in `source-exchange-rates-tutorial/source_exchange_rates_tutorial/spec.yaml`
```yaml
documentationUrl: https://docs.airbyte.io/integrations/sources/exchangeratesapi
connectionSpecification:
$schema: http://json-schema.org/draft-07/schema#
title: exchangeratesapi.io Source Spec
type: object
required:
- access_key
- base
additionalProperties: true
properties:
access_key:
type: string
description: >-
Your API Access Key. See here. The key is
case sensitive.
airbyte_secret: true
base:
type: string
description: >-
ISO reference currency. See here.
examples:
- EUR
- USD
```
2. We also need to fill in the connection config in the `secrets/config.json`
Because of the sensitive nature of the access key, we recommend storing this config in the `secrets` directory because it is ignored by git.
```bash
$ echo '{"access_key": "", "base": "USD"}' > secrets/config.json
```
## Updating the connector definition
Next, we'll update the connector definition (`source-exchange-rates-tutorial/source_exchange_rates_tutorial/exchange_rates_tutorial.yaml`). It was generated by the code generation script.
More details on the connector definition file can be found in the [overview](../overview.md) and [connection definition](../yaml-structure.md) sections.
Let's fill this out these TODOs with the information found in the [Exchange Rates API docs](https://apilayer.com/marketplace/exchangerates_data-api).
1. First, let's rename the stream from `customers` to `rates`, and update the primary key to `date`.
```yaml
streams:
- type: DeclarativeStream
$options:
name: "rates"
primary_key: "date"
```
and update the references in the `check` block
```yaml
check:
type: CheckStream
stream_names: [ "rates" ]
```
Adding the reference in the `check` tells the `check` operation to use that stream to test the connection.
2. Next we'll set the base url.
According to the API documentation, the base url is `"https://api.apilayer.com"`.
```yaml
definitions:
<...>
retriever:
type: SimpleRetriever
$options:
url_base: "https://api.apilayer.com"
```
3. We can fetch the latest data by submitting a request to the `/latest` API endpoint. This path is specific to the stream, so we'll set it within the `rates_stream` definition, at the `retriever` level.
```yaml
streams:
- type: DeclarativeStream
$options:
name: "rates"
primary_key: "date"
schema_loader:
$ref: "*ref(definitions.schema_loader)"
retriever:
$ref: "*ref(definitions.retriever)"
requester:
$ref: "*ref(definitions.requester)"
path: "/exchangerates_data/latest"
```
4. Next, we'll set up the authentication.
The Exchange Rates API requires an access key to be passed as header named "apikey".
This can be done using an `ApiKeyAuthenticator`, which we'll configure to point to the config's `access_key` field.
```yaml
definitions:
<...>
requester:
type: HttpRequester
name: "{{ options['name'] }}"
http_method: "GET"
authenticator:
type: ApiKeyAuthenticator
header: "apikey"
api_token: "{{ config['access_key'] }}"
```
5. According to the ExchangeRatesApi documentation, we can specify the base currency of interest in a request parameter. Let's assume the user will configure this via the connector configuration in parameter called `base`; we'll pass the value input by the user as a request parameter:
```yaml
definitions:
<...>
requester:
<...>
request_options_provider:
request_parameters:
base: "{{ config['base'] }}"
```
The full connector definition should now look like
```yaml
version: "0.1.0"
definitions:
schema_loader:
type: JsonSchema
file_path: "./source_exchange_rates_tutorial/schemas/{{ options['name'] }}.json"
selector:
type: RecordSelector
extractor:
type: DpathExtractor
field_pointer: [ ]
requester:
type: HttpRequester
name: "{{ options['name'] }}"
http_method: "GET"
authenticator:
type: ApiKeyAuthenticator
header: "apikey"
api_token: "{{ config['access_key'] }}"
request_options_provider:
request_parameters:
base: "{{ config['base'] }}"
retriever:
type: SimpleRetriever
$options:
url_base: "https://api.apilayer.com"
name: "{{ options['name'] }}"
primary_key: "{{ options['primary_key'] }}"
record_selector:
$ref: "*ref(definitions.selector)"
paginator:
type: NoPagination
streams:
- type: DeclarativeStream
$options:
name: "rates"
primary_key: "date"
schema_loader:
$ref: "*ref(definitions.schema_loader)"
retriever:
$ref: "*ref(definitions.retriever)"
requester:
$ref: "*ref(definitions.requester)"
path: "/exchangerates_data/latest"
check:
type: CheckStream
stream_names: [ "rates" ]
```
We can now run the `check` operation, which verifies the connector can connect to the API source.
```bash
$ python main.py check --config secrets/config.json
```
which should now succeed with logs similar to:
```
{"type": "LOG", "log": {"level": "INFO", "message": "Check succeeded"}}
{"type": "CONNECTION_STATUS", "connectionStatus": {"status": "SUCCEEDED"}}
```
## Next steps
Next, we'll [extract the records from the response](4-reading-data.md)
## More readings
- [Connector definition YAML file](../yaml-structure.md)
- [Config-based connectors overview](../overview.md)
- [Authentication](../authentication.md)
- [Request options providers](../request-options.md)
- [Schema definition](../../cdk-python/schemas.md)
- [Connector specification reference](../../connector-specification-reference.md)
- [Beginner's guide to catalog](../../../understanding-airbyte/beginners-guide-to-catalog.md)