> ## Documentation Index
> Fetch the complete documentation index at: https://docs.costory.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Terraform provider for Costory

> Install the Costory Terraform provider, authenticate with an API token, and manage billing datasources, enrichments and teams as code.

The [Costory Terraform provider](https://registry.terraform.io/providers/costory-io/costory/latest/docs) (`costory-io/costory`) calls the Costory API from your Terraform configuration. You can create billing datasources, publish [enrichments](https://docs.costory.io/features/tagging/enrichments.md), and manage [teams](https://docs.costory.io/features/teams.md) and their members, then review every change in a pull request before `terraform apply`. The source is on [GitHub](https://github.com/costory-io/terraform-provider-costory).

## Install the provider

Declare the provider in your configuration, then run `terraform init`.

```hcl theme={null}
terraform {
  required_providers {
    costory = {
      source  = "costory-io/costory"
      version = ">= 0.1.0"
    }
  }
}
```

The enrichment resources need version 0.3.1 or later.

## Authenticate

**1. Create an API token**

In the [Costory app](https://app.costory.io/), open your organization name (top-right) and go to **API Tokens**. You can create a user-scoped token, or an organization-scoped token if you are an admin. See [API overview](https://docs.costory.io/api-reference/overview.md#authentication).

**2. Pass the token to the provider**

Declare the token as a sensitive variable and set it in `terraform.tfvars` or as `TF_VAR_costory_api_token`.

```hcl theme={null}
variable "costory_api_token" {
  type        = string
  description = "Costory API token."
  sensitive   = true
}

provider "costory" {
  token = var.costory_api_token
}
```

| Argument | Required | Description |
| - | - | - |
| `token` | Yes | Costory API token. Sensitive. |
| `base_url` | No | Costory API base URL. Defaults to `https://app-api.costory.io`. |

Writing enrichments requires the API token of an organization admin.

## Look up the Costory service account

The `costory_service_account` data source returns the Costory service account name (`service_account`) and subscription IDs (`sub_ids`). The AWS and Google Cloud examples use it to grant Costory read access to your billing exports.

```hcl theme={null}
data "costory_service_account" "current" {}

output "service_account" {
  value = data.costory_service_account.current.service_account
}
```

## Billing datasources

Each billing datasource is one resource. Costory validates the connection when you apply, so a wrong credential or missing permission fails before any sync starts. `terraform destroy` deletes the datasource and permanently deletes the data it ingested. See [Billing data](https://docs.costory.io/setup/billing) for history and refresh details.

The examples below assume the provider block above. Secrets are passed as sensitive variables.

| Resource | Provider | Setup guide |
| - | - | - |
| [`costory_billing_datasource_aiven`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_aiven) | Aiven | [Guide](https://docs.costory.io/setup/billing/aiven.md) |
| [`costory_billing_datasource_anthropic`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_anthropic) | Anthropic Console (API usage) | [Guide](https://docs.costory.io/setup/billing/anthropic.md) |
| [`costory_billing_datasource_anthropic_claude_ai`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_anthropic_claude_ai) | Anthropic claude.ai | [Guide](https://docs.costory.io/setup/billing/anthropic.md) |
| [`costory_billing_datasource_aws`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_aws) | AWS (CUR 2.0) | [Guide](https://docs.costory.io/setup/billing/aws.md) |
| [`costory_billing_datasource_azure`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_azure) | Azure Cost Management | [Guide](https://docs.costory.io/setup/billing/azure.md) |
| [`costory_billing_datasource_clickhouse_cloud`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_clickhouse_cloud) | ClickHouse Cloud | [Guide](https://docs.costory.io/setup/billing/clickhouse.md) |
| [`costory_billing_datasource_cloudflare`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_cloudflare) | Cloudflare | [Guide](https://docs.costory.io/setup/billing/cloudflare.md) |
| [`costory_billing_datasource_confluent`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_confluent) | Confluent Cloud | [Guide](https://docs.costory.io/setup/billing/confluent.md) |
| [`costory_billing_datasource_cursor`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_cursor) | Cursor | [Guide](https://docs.costory.io/setup/billing/cursor.md) |
| [`costory_billing_datasource_custom_bigquery`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_custom_bigquery) | Custom billing table in BigQuery | [Guide](https://docs.costory.io/setup/billing/focus.md) |
| [`costory_billing_datasource_datadog`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_datadog) | Datadog | [Guide](https://docs.costory.io/setup/billing/datadog.md) |
| [`costory_billing_datasource_elastic_cloud`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_elastic_cloud) | Elastic Cloud | [Guide](https://docs.costory.io/setup/billing/elastic-cloud.md) |
| [`costory_billing_datasource_gcp`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_gcp) | Google Cloud (BigQuery billing export) | [Guide](https://docs.costory.io/setup/billing/gcp.md) |
| [`costory_billing_datasource_gcp_cud_export`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_gcp_cud_export) | Google Cloud CUD export | [Guide](https://docs.costory.io/setup/billing/gcp-cud-metadata.md) |
| [`costory_billing_datasource_openai`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_openai) | OpenAI | [Guide](https://docs.costory.io/setup/billing/openai.md) |
| [`costory_billing_datasource_scaleway`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_scaleway) | Scaleway | [Guide](https://docs.costory.io/setup/billing/scaleway.md) |
| [`costory_billing_datasource_snowflake`](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_snowflake) | Snowflake | [Guide](https://docs.costory.io/setup/billing/snowflake.md) |

> [accordion] Aiven: costory\_billing\_datasource\_aiven
>
> Field details: [Aiven setup](https://docs.costory.io/setup/billing/aiven.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_aiven" "main" {
>   name            = "Aiven Billing"
>   api_secret      = var.aiven_api_secret
>   organization_id = "aiven-organization-id"
> }
> ```

> [accordion] Anthropic Console (API usage): costory\_billing\_datasource\_anthropic
>
> Field details: [Anthropic Console (API usage) setup](https://docs.costory.io/setup/billing/anthropic.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_anthropic" "main" {
>   name          = "Anthropic Billing"
>   admin_api_key = var.anthropic_admin_api_key
> }
> ```

> [accordion] Anthropic claude.ai: costory\_billing\_datasource\_anthropic\_claude\_ai
>
> Field details: [Anthropic claude.ai setup](https://docs.costory.io/setup/billing/anthropic.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_anthropic_claude_ai" "main" {
>   name              = "Anthropic Claude AI Billing"
>   analytics_api_key = var.anthropic_claude_ai_analytics_api_key
>   account_name      = "acme"
> }
> ```

> [accordion] AWS (CUR 2.0): costory\_billing\_datasource\_aws
>
> The bucket, IAM role and CUR 2.0 export come from the full configuration in [AWS billing setup](https://docs.costory.io/setup/billing/aws.md). The resource below is the Costory part.
>
> ```hcl theme={null}
> resource "costory_billing_datasource_aws" "main" {
>   name                   = "AWS CUR ${var.s3_name}"
>   bucket_name            = aws_s3_bucket.s3_client_bucket.bucket
>   role_arn               = aws_iam_role.costory_federated_role.arn
>   prefix                 = var.s3_prefix
>   eks_split_data_enabled = true
>   depends_on             = [aws_bcmdataexports_export.cur_report_definition]
> }
> ```

> [accordion] Azure Cost Management: costory\_billing\_datasource\_azure
>
> The storage account, container, SAS URL and exports come from the full configuration in [Azure billing setup](https://docs.costory.io/setup/billing/azure.md). The resource below is the Costory part.
>
> ```hcl theme={null}
> resource "costory_billing_datasource_azure" "main" {
>   name                 = "Azure Production"
>   sas_url              = local.blob_endpoint_with_sas
>   storage_account_name = azurerm_storage_account.cost_exports.name
>   container_name       = azurerm_storage_container.billing.name
>   actuals_path         = "actuals/${local.actuals_export_name}"
>   amortized_path       = "amortized/${local.amortized_export_name}"
> }
> ```

> [accordion] ClickHouse Cloud: costory\_billing\_datasource\_clickhouse\_cloud
>
> Field details: [ClickHouse Cloud setup](https://docs.costory.io/setup/billing/clickhouse.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_clickhouse_cloud" "main" {
>   name            = "ClickHouse Cloud Billing"
>   key_id          = "key-id"
>   key_secret      = var.clickhouse_cloud_key_secret
>   organization_id = "org-123"
> }
> ```

> [accordion] Cloudflare: costory\_billing\_datasource\_cloudflare
>
> Field details: [Cloudflare setup](https://docs.costory.io/setup/billing/cloudflare.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_cloudflare" "main" {
>   name       = "Cloudflare Billing"
>   api_token  = var.cloudflare_api_token
>   account_id = "cloudflare-account-id"
> }
> ```

> [accordion] Confluent Cloud: costory\_billing\_datasource\_confluent
>
> Field details: [Confluent Cloud setup](https://docs.costory.io/setup/billing/confluent.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_confluent" "main" {
>   name       = "Confluent Billing"
>   api_key    = var.confluent_api_key
>   api_secret = var.confluent_api_secret
> }
> ```

> [accordion] Cursor: costory\_billing\_datasource\_cursor
>
> Field details: [Cursor setup](https://docs.costory.io/setup/billing/cursor.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_cursor" "main" {
>   name          = "Cursor Billing"
>   admin_api_key = var.cursor_admin_api_key
> }
> ```

> [accordion] Custom billing table in BigQuery: costory\_billing\_datasource\_custom\_bigquery
>
> Maps the columns of your own BigQuery cost table to Costory billing fields. `billed_cost` is required. Full schema: [Registry](https://registry.terraform.io/providers/costory-io/costory/latest/docs/resources/billing_datasource_custom_bigquery).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_custom_bigquery" "main" {
>   name          = "Custom BigQuery Billing"
>   bq_table_path = "my-project.custom.costs"
>   provider_name = "acme"
>
>   mapping = {
>     billed_cost  = "cost"
>     service_name = "sku"
>   }
> }
> ```

> [accordion] Datadog: costory\_billing\_datasource\_datadog
>
> Field details: [Datadog setup](https://docs.costory.io/setup/billing/datadog.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_datadog" "main" {
>   name            = "Datadog Billing"
>   api_key         = var.datadog_api_key
>   application_key = var.datadog_application_key
>   region          = "datadoghq.com"
> }
> ```

> [accordion] Elastic Cloud: costory\_billing\_datasource\_elastic\_cloud
>
> Field details: [Elastic Cloud setup](https://docs.costory.io/setup/billing/elastic-cloud.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_elastic_cloud" "main" {
>   name            = "Elastic Cloud Billing"
>   api_key         = var.elastic_cloud_api_key
>   organization_id = var.elastic_cloud_organization_id
> }
> ```

> [accordion] Google Cloud (BigQuery billing export): costory\_billing\_datasource\_gcp
>
> The example grants the Costory service account read access to your billing export dataset, then creates the datasource. Full walkthrough: [Google Cloud billing setup](https://docs.costory.io/setup/billing/gcp.md).
>
> ```hcl theme={null}
> locals {
>   bigquery_roles = toset([
>     "roles/bigquery.metadataViewer",
>     "roles/bigquery.dataViewer",
>   ])
>   # Set the BigQuery project, dataset, and table IDs where your detailed billing data is exported.
>   bigquery_project_id = "my-project"
>   bigquery_dataset_id = "billing_export"
>   bigquery_table_id   = "gcp_billing_export_v1_0123"
> }
>
> resource "google_bigquery_dataset_iam_member" "costory_access" {
>   for_each   = local.bigquery_roles
>   project    = local.bigquery_project_id
>   dataset_id = local.bigquery_dataset_id
>   role       = each.key
>   member     = "serviceAccount:${data.costory_service_account.current.service_account}"
> }
>
> resource "costory_billing_datasource_gcp" "main" {
>   name                = "GCP Billing Export"
>   bq_uri              = "${local.bigquery_project_id}.${local.bigquery_dataset_id}.${local.bigquery_table_id}"
>   is_detailed_billing = true
>   depends_on          = [google_bigquery_dataset_iam_member.costory_access]
> }
> ```

> [accordion] Google Cloud CUD export: costory\_billing\_datasource\_gcp\_cud\_export
>
> Field details: [Google Cloud CUD export setup](https://docs.costory.io/setup/billing/gcp-cud-metadata.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_gcp_cud_export" "main" {
>   name          = "GCP CUD Export"
>   bq_table_path = "my-project.billing.cud_export"
> }
> ```

> [accordion] OpenAI: costory\_billing\_datasource\_openai
>
> Field details: [OpenAI setup](https://docs.costory.io/setup/billing/openai.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_openai" "main" {
>   name          = "OpenAI Billing"
>   admin_api_key = var.openai_admin_api_key
> }
> ```

> [accordion] Scaleway: costory\_billing\_datasource\_scaleway
>
> Field details: [Scaleway setup](https://docs.costory.io/setup/billing/scaleway.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_scaleway" "main" {
>   name            = "Scaleway Billing"
>   secret_key      = var.scaleway_secret_key
>   organization_id = "scaleway-organization-id"
> }
> ```

> [accordion] Snowflake: costory\_billing\_datasource\_snowflake
>
> Field details: [Snowflake setup](https://docs.costory.io/setup/billing/snowflake.md).
>
> ```hcl theme={null}
> resource "costory_billing_datasource_snowflake" "main" {
>   name           = "Snowflake Billing"
>   integration_id = "snowflake-integration-id"
> }
> ```

## Enrichments

`costory_enrichment` stores one YAML lookup file as a draft. `costory_enrichments_publish` publishes every draft in one transaction after the files are written, and removes the enrichments whose file you deleted. See [Publish with Terraform](https://docs.costory.io/features/tagging/enrichments.md#publish-with-terraform) for the file format.

```hcl theme={null}
# One resource per YAML file in ./enrichments. Applying stores drafts;
# costory_enrichments_publish makes them live.
resource "costory_enrichment" "all" {
  for_each = fileset("${path.module}/enrichments", "*.yaml")

  name = trimsuffix(each.value, ".yaml")
  file = "${path.module}/enrichments/${each.value}"
}

# Publishes every draft in one transaction after the enrichments are written,
# and removes the enrichments whose file was deleted.
resource "costory_enrichments_publish" "this" {
  enrichments = { for enrichment in costory_enrichment.all : enrichment.name => enrichment.content_sha256 }
}
```

## Teams and members

`costory_team` creates a `PUBLIC` or `PRIVATE` team. `costory_team_member` adds a member by `email` or `user_id`, with the `OWNER` or `MEMBER` role. Team scopes are still managed in the UI. See [Teams](https://docs.costory.io/features/teams.md).

```hcl theme={null}
resource "costory_team" "engineering" {
  name        = "Engineering"
  description = "All engineering members"
  visibility  = "PUBLIC"
}

variable "team_members" {
  type = map(object({
    email = string
    role  = string
  }))
  default = {
    alice = { email = "alice@example.com", role = "OWNER" }
    bob   = { email = "bob@example.com", role = "MEMBER" }
    carol = { email = "carol@example.com", role = "MEMBER" }
  }
}

resource "costory_team_member" "members" {
  for_each = var.team_members

  team_id = costory_team.engineering.id
  email   = each.value.email
  role    = each.value.role
}
```

## Related

> [card] [Billing data](https://docs.costory.io/setup/billing)
>
> Every provider, history and refresh

> [card] [Enrichments](https://docs.costory.io/features/tagging/enrichments.md)
>
> YAML lookup files you keep in git

> [card] [Teams](https://docs.costory.io/features/teams.md)
>
> Team creation, members and scopes

> [card] [Terraform Registry](https://registry.terraform.io/providers/costory-io/costory/latest/docs)
>
> Full schema for every resource


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.