# Destination YAML Reference


This guide is the YAML reference for destination resources in a Rudder CLI project.

## Overview

Set `kind` to `destination`. Each file defines **one** destination. You can store the file anywhere under the project root — Rudder CLI scans the directory recursively.

{{< warning >}}
**Destination support is experimental**.

Enable `destinationSupport` (`RUDDERSTACK_X_DESTINATION_SUPPORT=true`) before you validate or apply destination specs. Rudder CLI currently supports Amazon S3 (`s3`). See [Supported destination types](#supported-destination-types).

If `config` references secrets as `{{ .VAR }}`, also enable variable substitution and pass `--var-file` on apply. See [How to Use Variable Substitution in Rudder CLI]({{< ref "dev-tools/rudder-cli/variable-substitution.md" >}}).
{{< /warning >}}

Local YAML uses **snake_case** config keys. Rudder CLI converts them to the API's camelCase at apply time. Do not put camelCase keys in the spec.

## Destination resources

The `spec` object has the following structure:

| Property | Type | <div style="width:300px">Description</div> |
| :----| :-----| :------|
| `id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Unique identifier for the destination within the project. Other specs reference it as `#destination:[id]`. |
| `display_name` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Name shown in the RudderStack dashboard. Must be 2–100 characters and contain only letters, digits, underscores, spaces, periods, and hyphens. Must be unique across destinations in the project. |
| `type` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Destination type. See [Supported destination types](#supported-destination-types). **Immutable** after apply — changing `type` fails the update. |
| `definition_version` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | Integer | Definition version for `type`. Set this to `1` — that is the current version for every registered destination. |
| `enabled` | Boolean | Whether the destination is enabled. If you omit this field, Rudder CLI creates the destination as **disabled**. Set `enabled: true` to deliver events after you connect a source. |
| `config` | Object | Per-type connection settings. Keys and validation rules come from the destination definition. Unknown envelope fields (siblings of these properties) fail validation. |
| `transformation` | String | Optional URN of a transformation in the same project — `#transformation:[transformation.id]`. The referenced transformation must exist in the project. |

{{< warning >}}
`type` is immutable. To send data to a different destination product, define a new destination resource rather than editing `type` on an existing one.
{{< /warning >}}

## Supported destination types

Use the `type` value in YAML. Rudder CLI currently supports Amazon S3.

{{< customreadfile "/includes/rudder-cli/unverified-destinations-later.md" >}}

| Destination | `type` |
| :------| :-------|
| Amazon S3 | `s3` |

Rudder CLI rejects any `type` that is not in this table. The dashboard supports more destinations than the CLI.

## Amazon S3 configuration

`config` for `type: s3` (`definition_version: 1`):

| Key | Type | Description |
| :----| :-----| :------|
| `bucket_name` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | S3 bucket name (1–100 characters). |
| `role_based_auth` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | Boolean | `true` for IAM role authentication; `false` for access keys. |
| `iam_role_arn` | String | IAM role ARN. **Required** when `role_based_auth` is `true`; do not set it when `role_based_auth` is `false`. |
| `access_key_id` | String | AWS access key ID. **Secret.** Required when `role_based_auth` is `false`; do not set it when `role_based_auth` is `true`. |
| `access_key` | String | AWS secret access key. **Secret.** Required when `role_based_auth` is `false`; do not set it when `role_based_auth` is `true`. |
| `prefix` | String | Optional object prefix (max 100 characters). |
| `enable_sse` | Boolean | Optional server-side encryption setting. |

`access_key_id` and `access_key` are secrets. Supply them as `{{ .VAR }}` references — see [Secret handling](#secret-handling).

Destination definitions also validate extra keys such as `consent_management`. `validate` reports unknown or invalid `config` keys for the selected `type`.

### Source-type-scoped keys

The S3 `config` block also accepts source-type-scoped keys such as `connection_mode` and `use_native_sdk`. Each nested key must be a source type that destination supports. Connection mode belongs on the destination spec, not on an [Event Stream connection]({{< ref "dev-tools/rudder-cli/yaml-connections.md" >}}).

## Examples

#### Amazon S3 with IAM role authentication

```yaml
version: rudder/v1
kind: destination
metadata:
  name: s3
spec:
  id: s3
  display_name: "S3 Destination"
  type: s3
  definition_version: 1
  enabled: true
  config:
    bucket_name: "my-rudder-bucket"
    prefix: "rudder-events"
    role_based_auth: true
    iam_role_arn: "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
```

#### Amazon S3 with access keys

```yaml
version: rudder/v1
kind: destination
metadata:
  name: s3
spec:
  id: s3
  display_name: "S3 Destination"
  type: s3
  definition_version: 1
  enabled: true
  config:
    bucket_name: "my-rudder-bucket"
    role_based_auth: false
    access_key_id: "{{ .AWS_ACCESS_KEY_ID }}"
    access_key: "{{ .AWS_SECRET_ACCESS_KEY }}"
```

#### Destination with a transformation

The transformation must exist in the same project. Rudder CLI creates or updates the destination, then links the transformation.

```yaml
version: rudder/v1
kind: destination
metadata:
  name: s3
spec:
  id: s3
  display_name: "S3 Destination"
  type: s3
  definition_version: 1
  enabled: true
  transformation: "#transformation:enrich-events"
  config:
    bucket_name: "my-rudder-bucket"
    role_based_auth: true
    iam_role_arn: "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
```

## Secret handling

Secret `config` keys (for example S3 `access_key` and `access_key_id`) must be `{{ .VARIABLE_NAME }}` references, not literals.

See [How to Use Variable Substitution in Rudder CLI]({{< ref "dev-tools/rudder-cli/variable-substitution.md" >}}).

## Import existing destinations

```bash
rudder-cli import workspace -l <project-directory>
```

Rudder CLI writes one file per destination under `imported/destinations/<id>.yaml`, converts config to snake_case, masks secrets as `{{ .VAR }}` placeholders, and records import metadata. Use import to bring destinations you created in the dashboard under CLI management.

Fill secret placeholders before apply. See [Fill placeholders after import]({{< ref "dev-tools/rudder-cli/variable-substitution.md#fill-placeholders-after-import" >}}).

See [How to Import Workspace Resources]({{< ref "dev-tools/rudder-cli/import-resources/" >}}) for the full import workflow.

## Validation rules

`rudder-cli validate` checks destination specs before apply. Failures block apply.

| Check | When it fails |
| :----| :-----|
| Required envelope fields | `id`, `display_name`, `type`, or `definition_version` is missing |
| `display_name` format | Value is outside 2–100 characters or uses characters other than letters, digits, underscores, spaces, periods, and hyphens |
| Duplicate `display_name` | Two destinations in the project share the same `display_name` |
| Unknown `type` | `type` is not a supported destination type (or `destinationSupport` is off) |
| Invalid `definition_version` | Version is not registered for that `type` |
| `config` shape | Required keys are missing, types are wrong, or mutually exclusive auth fields are combined (for example S3 role ARN together with access keys) |
| Unsupported source-type key | A nested `connection_mode` / `use_native_sdk` key uses a source type the destination does not support |
| Transformation reference | `transformation` is not `#transformation:[id]`, or that transformation is not in the project |

Plan limits, OAuth token state, and live warehouse connectivity are not checked locally. The server returns those errors on apply.

## See more

- [Manage Destinations using Rudder CLI]({{< ref "dev-tools/rudder-cli/destinations.md" >}}) for feature overview, and the [Destinations walkthrough]({{< ref "dev-tools/rudder-cli/destinations-walkthrough.md" >}}) for step-by-step setup
- [How to Use Variable Substitution in Rudder CLI]({{< ref "dev-tools/rudder-cli/variable-substitution.md" >}}) for secret `config` keys
- [Connection YAML Reference]({{< ref "dev-tools/rudder-cli/yaml-connections.md" >}}) to link this destination to a source
- [Transformation YAML Reference]({{< ref "dev-tools/rudder-cli/yaml-transformations.md" >}}) for the `#transformation:` target

