> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.ampdb.io/api/mcp` to find what you need.

# Managing Providers

A [provider](/providers) is a connection to a source of chain data, like an Ethereum RPC endpoint. Amp has no chain
connections built in: a [raw dataset](/datasets/raw-datasets) extracts through the providers registered for its kind
and network. This page covers registering, listing, inspecting, and removing providers. The fields each kind of
provider takes are on its own page, like [EVM RPC](/providers/evm-rpc).

You manage providers with [`ampctl provider`](/clis/ampctl/provider) or the
[Admin API](/managing-amp/admin-api/providers).

## Prerequisites

* Amp running, with its Admin API reachable, and `ampctl` installed, as in
  [Managing Datasets](/managing-amp/datasets#prerequisites).
* For the examples: an Ethereum RPC endpoint, in an environment variable:

  ```bash
  export RPC_URL=…
  ```

## Register a provider

Describe the provider in a TOML file: its `kind`, the `network` it serves, and the fields its kind takes. For an EVM RPC
endpoint:

```bash
cat > mainnet.toml <<EOF
kind = "evm-rpc"
network = "mainnet"
url = "$RPC_URL"
EOF
```

Then register it under a name:

:::code-group
```bash [ampctl]
ampctl provider register mainnet_rpc ./mainnet.toml
```

```bash [Admin API]
curl -X POST http://localhost:1610/providers \
  -H 'Content-Type: application/json' \
  -d "{\"name\": \"mainnet_rpc\", \"kind\": \"evm-rpc\", \"network\": \"mainnet\", \"url\": \"$RPC_URL\"}"
```
:::

The Admin API answers `201 Created`. `ampctl` converts the TOML file to the JSON the API takes, so the API's body has
the same fields, plus `name`.

| Argument        | Type          | Description                                                                                                      |
| --------------- | ------------- | ---------------------------------------------------------------------------------------------------------------- |
| `PROVIDER_NAME` | provider name | The name to register it under: lowercase letters, digits, and underscores, starting with a letter or underscore. |
| `FILE`          | path or URL   | The TOML file: a local path, or a `file://`, `s3://`, `gs://`, or `az://` URL.                                   |

* **Registering a name again replaces it.** A running deployment keeps the configuration it started with: to apply the
  change, [stop](/managing-amp/datasets#stop-a-deployment) the deployment, then deploy it again.
* **A dataset uses every matching provider.** A raw dataset's deployment uses the providers registered for its kind and
  network, moving to the next one each time it retries. To use only one, deploy with
  [`--provider`](/managing-amp/datasets#--provider).
* **Amp stores each provider as a TOML file** in its providers directory, named after the provider, like
  `mainnet_rpc.toml` (see [`providers_dir`](/running-amp/configuration-reference#providers_dir)).
* **Reading the file from object storage** uses that store's usual credentials from the environment, like
  `AWS_ACCESS_KEY_ID`, `GOOGLE_APPLICATION_CREDENTIALS`, or `AZURE_STORAGE_ACCOUNT_NAME`.

### Keep secrets out of the configuration

A credential written in a provider's configuration is stored as is, and returned to anyone who can read it. Write a
reference to an environment variable instead, as `${NAME}`, and set the variable where Amp runs:

```bash
cat > mainnet.toml <<'EOF'
kind = "evm-rpc"
network = "mainnet"
url = "https://your-ethereum-rpc.example.com"
auth_token = "${RPC_TOKEN}"
EOF
ampctl provider register mainnet_rpc ./mainnet.toml
```

Amp stores the reference, not its value: it reads `RPC_TOKEN` from its environment each time a job loads the
provider. So set the variable in the environment of every `ampd` process that uses providers (`ampd solo`, or the
[workers](/running-amp/worker) and the [query server](/running-amp/query-server)), not in the shell you run `ampctl`
from. If it isn't set there, jobs that use the provider fail.

Amp stores the reference as you wrote it, so `ampctl provider inspect` shows `${RPC_TOKEN}`.

## List providers

:::code-group
```bash [ampctl]
ampctl provider list
```

```bash [Admin API]
curl http://localhost:1610/providers
```
:::

```
Providers:
  mainnet_rpc (evm-rpc)
```

`ampctl provider ls` is an alias. With `--json`, and from the Admin API, each provider comes with its whole
configuration, as [inspect](/managing-amp/providers#inspect-a-provider) shows it.

## Inspect a provider

:::code-group
```bash [ampctl]
ampctl provider inspect mainnet_rpc
```

```bash [Admin API]
curl http://localhost:1610/providers/mainnet_rpc
```
:::

```json
{
  "name": "mainnet_rpc",
  "kind": "evm-rpc",
  "network": "mainnet",
  "url": "https://your-ethereum-rpc.example.com",
  "auth_token": "${RPC_TOKEN}"
}
```

`ampctl provider get` is an alias. The configuration is returned as stored: references stay references, but anything
written in plain text, like a URL with a key in it, is returned in plain text too.

## Remove a provider

:::code-group
```bash [ampctl]
ampctl provider rm mainnet_rpc
```

```bash [Admin API]
curl -X DELETE http://localhost:1610/providers/mainnet_rpc
```
:::

`ampctl provider remove` is an alias. The Admin API answers `204 No Content`, even when there was no such provider, so
you can safely run it again. There's no way to undo it, and deployments that extract through the provider fail once no
other provider of their kind and network is left.

## Export destinations

Providers of the `adbc-postgres` and `adbc-snowflake` kinds aren't sources: they're databases that
[export jobs](/managing-amp/pipelines) write datasets to. You register and remove them the same way, with more rules for
their names, secrets, and the other providers they depend on. See
[Destinations](/managing-amp/pipelines/destinations).

## Errors

| Error code                                 | Status | Cause                                                                                                      |
| ------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------- |
| `INVALID_REQUEST_BODY`                     | `400`  | The request body isn't valid JSON.                                                                         |
| `INVALID_PROVIDER_NAME`                    | `400`  | The name has characters other than lowercase letters, digits, and underscores, or starts with a digit.     |
| `DATA_CONVERSION_ERROR`                    | `400`  | The configuration can't be stored as TOML, like one with a `null` value or an array that mixes types.      |
| `PROVIDER_NOT_FOUND`                       | `404`  | No provider has that name. `ampctl` says `provider 'mainnet_rpc' not found`.                               |
| `PROVIDER_CONFLICT`                        | `409`  | Someone registered the same name at the same time. Try again.                                              |
| `PROVIDER_KIND_CONFLICT`                   | `409`  | The name belongs to an export destination, and the new kind isn't one. Remove it first.                    |
| `PROVIDER_REFERENCED`                      | `409`  | Other export destinations use this one's credentials. The message names them; remove or change them first. |
| `PROVIDER_IN_USE`                          | `409`  | Running exports are connected to this export destination. Stop them first.                                 |
| `PROVIDER_CONVERSION_ERROR`, `STORE_ERROR` | `500`  | Amp couldn't read or write the provider's configuration.                                                   |

Export destinations have errors of their own, in [Destinations](/managing-amp/pipelines/destinations). The
[Admin API reference](/managing-amp/admin-api/providers) lists every error each endpoint returns.
