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

# Terraform provider

> Manage your Braintrust organization with Terraform. Define projects, access, secrets, and automations as code that you can review and version.

> [!WARNING]
>
> The Terraform provider is in [public preview](https://www.braintrust.dev/docs/feature-lifecycle.md) and can change before reaching general availability.

The Braintrust Terraform provider manages your organization's resources as code. Published on the Terraform Registry as [`braintrustdata/braintrust`](https://registry.terraform.io/providers/braintrustdata/braintrust/latest/docs), it covers projects, datasets, functions, scores, tags, permission groups, project groups, roles, ACLs, service accounts and tokens, AI provider secrets, environment variables, automations (including retention), saved views, and MCP servers.

The [Braintrust Terraform Registry entry](https://registry.terraform.io/providers/braintrustdata/braintrust/latest/docs) documents every resource and data source, including their arguments. The provider's source code, examples, and releases are in the [`terraform-provider-braintrust`](https://github.com/braintrustdata/terraform-provider-braintrust) GitHub repository.

> [!NOTE]
>
> The provider manages resources inside a Braintrust organization that already exists, and doesn't provision cloud infrastructure. To deploy a self-hosted data plane in your own cloud account, use the [data plane Terraform modules](https://www.braintrust.dev/docs/admin/self-hosting/deploy.md).

## What to manage with Terraform

Terraform works best for stable configuration that a platform team governs centrally and shares across teams or environments:

* **Access and identity**: Permission groups, roles, ACLs, service accounts, and service tokens.
* **Project scaffolding**: Projects, score definitions, tags, and datasets (the containers, not their rows).
* **Organization policy**: AI provider secrets, environment variables, and automations, including retention.

Keep content that changes often in your application code and its deployment pipeline instead:

* **Frequently changing prompts and functions**: Push these with the SDK or [`bt functions push`](https://www.braintrust.dev/docs/reference/cli/functions) so they ship with your application. Terraform doesn't build or upload code bundles, so functions with local dependencies need the push workflow.
* **Data and events**: Dataset rows, logs, and experiment results.

The provider doesn't create organizations, invite members, or create user API keys. [Invite members](https://www.braintrust.dev/docs/admin/organizations.md#invite-members) in Braintrust, then reference them in Terraform by email.

## Example: Set up a support team

This example walks through a realistic configuration, from an empty directory to a working `terraform apply`, that shows how the Braintrust Terraform provider's resources fit together so you can adapt them to your own organization.

The configuration sets up Braintrust for a support team that builds a customer support bot, with:

* Production and staging projects, so changes tested in staging don't affect production.
* Two permission groups: engineers who build in both projects, and reviewers who view results without changing anything.
* A shared prompt that triages support tickets, and a scorer that checks the prompt's answers.

Each step adds blocks to the same `main.tf` file. The [complete configuration](#complete-configuration) is at the end of the example.

### Prerequisites

> [!NOTE]
>
> Custom permission groups and project-level permissions are only available on the [Enterprise plan](https://www.braintrust.dev/docs/plans-and-limits.md#plans).

The example also requires:

* Terraform 1.0.3 or later.
* The members you want in each group, already [invited](https://www.braintrust.dev/docs/admin/organizations.md#invite-members) to your organization.
* A Braintrust [API key](https://www.braintrust.dev/docs/admin/organizations.md#manage-api-keys) or [service token](https://www.braintrust.dev/docs/admin/organizations.md#create-service-tokens) for your organization.

### 1. Install and authenticate

Terraform needs the Braintrust provider and a credential before it can change anything in your organization.

The `terraform` block names the provider to download from the Terraform Registry. Uncomment `version` and set it to the latest release so that future provider updates don't change your configuration's behavior unexpectedly. The `provider` block configures the provider. Left empty, it reads your credential from the `BRAINTRUST_API_KEY` environment variable.

In an empty directory, create `main.tf`:

```hcl main.tf wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
terraform {
  required_providers {
    braintrust = {
      source = "braintrustdata/braintrust"
      # version = "x.y.z" # Pin to the latest version on the Terraform Registry
    }
  }
}

provider "braintrust" {}
```

Set your API key, then run `terraform init` to download the provider:

```bash wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
export BRAINTRUST_API_KEY="<your-api-key>"
terraform init
```

If your organization uses the EU data plane or a self-hosted data plane, also [set the API URL](#set-the-api-url). To run Terraform from a CI pipeline, use a service token instead of a personal API key. See [Authenticate in CI](#authenticate-in-ci).

### 2. Look up members

Permission groups identify members by user ID, not email. The `braintrust_user` data source looks up an existing member by email and returns the user ID that [step 4](#4-create-permission-groups-and-grant-access) needs, without changing anything in Braintrust.

The code lists the engineer and reviewer emails in two variables, then looks up each email. Replace the default emails with your members' emails. Each email must belong to a member of your organization.

```hcl main.tf expandable wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
variable "engineer_emails" {
  description = "Members who build and iterate in both projects"
  type        = list(string)
  default     = ["alice@example.com", "bob@example.com"] # Replace with your members' emails
}

variable "reviewer_emails" {
  description = "Members who review results without changing anything"
  type        = list(string)
  default     = ["carol@example.com"] # Replace with your members' emails
}

data "braintrust_user" "engineers" {
  for_each = toset(var.engineer_emails)
  email    = each.value
}

data "braintrust_user" "reviewers" {
  for_each = toset(var.reviewer_emails)
  email    = each.value
}
```

### 3. Create projects

In this example, the support team needs two projects: one for the live support bot, and a staging project for testing changes before they reach production. Keeping them separate also lets the team grant access to each one independently. The `braintrust_project` resource creates both.

```hcl main.tf wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
resource "braintrust_project" "support_bot" {
  name        = "Support bot"
  description = "Customer support assistant"
}

resource "braintrust_project" "support_bot_staging" {
  name        = "Support bot (staging)"
  description = "Staging environment for the customer support assistant"
}
```

If a project with the same name already exists in your organization, `terraform apply` fails instead of taking it over. [Import the project](#import-existing-resources) first.

### 4. Create permission groups and grant access

Engineers build and change things, while reviewers only view results, so the two groups need different access to both projects.

Braintrust grants access through three pieces, each with its own block in the provider:

* **[Permission groups](https://www.braintrust.dev/docs/admin/access-control.md)** (`braintrust_group`) let you grant access to several members at once.
* **Roles** (`braintrust_role` data source) are sets of permissions. Braintrust includes built-in roles such as `Engineer` and `Viewer`.
* **ACLs** (`braintrust_acl`) grant one group one role on one object, such as a project.

The code gives the **Support engineers** group the `Engineer` role and the **Support reviewers** group the `Viewer` role, with one ACL for each group on each project:

```hcl main.tf expandable wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
resource "braintrust_group" "support_engineers" {
  name         = "Support engineers"
  description  = "Build and evaluate the support bot"
  member_users = [for user in data.braintrust_user.engineers : user.id]
}

resource "braintrust_group" "support_reviewers" {
  name         = "Support reviewers"
  description  = "Review support bot results"
  member_users = [for user in data.braintrust_user.reviewers : user.id]
}

data "braintrust_role" "engineer" {
  name = "Engineer"
}

data "braintrust_role" "viewer" {
  name = "Viewer"
}

locals {
  support_projects = {
    production = braintrust_project.support_bot.id
    staging    = braintrust_project.support_bot_staging.id
  }
}

resource "braintrust_acl" "engineers" {
  for_each = local.support_projects

  object_type = "project"
  object_id   = each.value
  group_id    = braintrust_group.support_engineers.id
  role_id     = data.braintrust_role.engineer.id
}

resource "braintrust_acl" "reviewers" {
  for_each = local.support_projects

  object_type = "project"
  object_id   = each.value
  group_id    = braintrust_group.support_reviewers.id
  role_id     = data.braintrust_role.viewer.id
}
```

If your organization has a custom role named `Engineer` or `Viewer`, looking up the role by name fails. Look it up by `id` instead.

If a group with the same name already exists, `terraform apply` fails instead of taking it over. [Import the group](#import-existing-resources) first, or use a different name.

**Grant access to every project**

These ACLs cover only the two support projects. To grant a group a role on every project in your organization, including projects created later, set `object_type` to `org_project` and `object_id` to your [organization ID](https://www.braintrust.dev/docs/admin/organizations.md#find-your-organization-id). Any project's `org_id` attribute holds that ID:

```hcl wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
resource "braintrust_acl" "reviewers_all_projects" {
  object_type = "org_project"
  object_id   = braintrust_project.support_bot.org_id
  group_id    = braintrust_group.support_reviewers.id
  role_id     = data.braintrust_role.viewer.id
}
```

### 5. Add a prompt and a scorer

The support bot needs a prompt that triages tickets and a scorer that checks the prompt's answers. Both change rarely and are shared across teams, which makes them a good fit for Terraform.

The `braintrust_function` resource manages prompts and functions such as scorers, tools, and preprocessors. Two arguments describe the function, and both take JSON strings in the shape the [Braintrust API](https://www.braintrust.dev/docs/api-reference/functions/create-function.md) accepts:

* `function_data_json` sets the function's type, such as `prompt` or `code`.
* `prompt_data_json` sets a prompt's messages and model. Only prompts use it.

The `jsonencode()` function turns Terraform values into these JSON strings, so you don't have to write raw JSON.

The code creates a prompt that classifies a ticket as billing, bug, or how-to. It also creates a scorer that returns 1 if the prompt's answer is one of those categories, and 0 if it isn't:

```hcl main.tf expandable wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
resource "braintrust_function" "triage_prompt" {
  project_id = braintrust_project.support_bot.id
  name       = "Triage ticket"
  slug       = "triage-ticket"

  function_data_json = jsonencode({ type = "prompt" })
  prompt_data_json = jsonencode({
    prompt = {
      type = "chat"
      messages = [
        {
          role    = "system"
          content = "Classify the support ticket as billing, bug, or how-to. Reply with the category only."
        },
        {
          role    = "user"
          content = "{{input}}"
        },
      ]
    }
    options = { model = "gpt-5-mini" }
  })
}

resource "braintrust_function" "category_scorer" {
  project_id    = braintrust_project.support_bot.id
  name          = "Valid category"
  slug          = "valid-category"
  function_type = "scorer"

  function_data_json = jsonencode({
    type = "code"
    data = {
      type            = "inline"
      runtime_context = { runtime = "node", version = "22" }
      code            = <<-JS
        function handler({ output }) {
          const categories = ["billing", "bug", "how-to"];
          return categories.includes(String(output).trim().toLowerCase()) ? 1 : 0;
        }
      JS
    }
  })
}
```

Manage each function from one place, either Terraform or your push workflow, but not both. Keep prompts that your application team changes often in application code. To reference a function that Terraform doesn't manage, such as one you push with [`bt functions push`](https://www.braintrust.dev/docs/reference/cli/functions), use the `braintrust_function` data source.

If a function with the same slug already exists in the project, `terraform apply` fails instead of overwriting it. [Import the function](#import-existing-resources) first, or use a different slug.

### 6. Apply and verify

With the configuration complete, Terraform can create everything in Braintrust.

`terraform plan` shows what Terraform will create, change, or delete, without changing anything. `terraform apply` shows the same plan, asks you to confirm, and then makes the changes.

```bash wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
terraform plan
terraform apply
```

After the apply completes, check that everything appears in Braintrust:

* The projects, in your organization's [project list](https://www.braintrust.dev/docs/admin/projects.md#view-projects)
* The groups, in ** Settings** > [** Permissions**](https://www.braintrust.dev/app/~/configuration/permissions/organization)
* The prompt and scorer, in the **Support bot** project's [** Prompts**](https://www.braintrust.dev/app/~/prompts) and [** Scorers**](https://www.braintrust.dev/app/~/scorers) pages

From here, change the configuration and run `terraform apply` again to update Braintrust. Terraform records what it created in a local state file, which can hold secrets. Before you manage your organization's real configuration, see [Use the provider in production](#use-the-provider-in-production).

### Complete configuration

The complete `main.tf` for this example:

```hcl main.tf expandable wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
terraform {
  required_providers {
    braintrust = {
      source = "braintrustdata/braintrust"
      # version = "x.y.z" # Pin to the latest version on the Terraform Registry
    }
  }
}

provider "braintrust" {}

variable "engineer_emails" {
  description = "Members who build and iterate in both projects"
  type        = list(string)
  default     = ["alice@example.com", "bob@example.com"] # Replace with your members' emails
}

variable "reviewer_emails" {
  description = "Members who review results without changing anything"
  type        = list(string)
  default     = ["carol@example.com"] # Replace with your members' emails
}

data "braintrust_user" "engineers" {
  for_each = toset(var.engineer_emails)
  email    = each.value
}

data "braintrust_user" "reviewers" {
  for_each = toset(var.reviewer_emails)
  email    = each.value
}

resource "braintrust_project" "support_bot" {
  name        = "Support bot"
  description = "Customer support assistant"
}

resource "braintrust_project" "support_bot_staging" {
  name        = "Support bot (staging)"
  description = "Staging environment for the customer support assistant"
}

resource "braintrust_group" "support_engineers" {
  name         = "Support engineers"
  description  = "Build and evaluate the support bot"
  member_users = [for user in data.braintrust_user.engineers : user.id]
}

resource "braintrust_group" "support_reviewers" {
  name         = "Support reviewers"
  description  = "Review support bot results"
  member_users = [for user in data.braintrust_user.reviewers : user.id]
}

data "braintrust_role" "engineer" {
  name = "Engineer"
}

data "braintrust_role" "viewer" {
  name = "Viewer"
}

locals {
  support_projects = {
    production = braintrust_project.support_bot.id
    staging    = braintrust_project.support_bot_staging.id
  }
}

resource "braintrust_acl" "engineers" {
  for_each = local.support_projects

  object_type = "project"
  object_id   = each.value
  group_id    = braintrust_group.support_engineers.id
  role_id     = data.braintrust_role.engineer.id
}

resource "braintrust_acl" "reviewers" {
  for_each = local.support_projects

  object_type = "project"
  object_id   = each.value
  group_id    = braintrust_group.support_reviewers.id
  role_id     = data.braintrust_role.viewer.id
}

resource "braintrust_function" "triage_prompt" {
  project_id = braintrust_project.support_bot.id
  name       = "Triage ticket"
  slug       = "triage-ticket"

  function_data_json = jsonencode({ type = "prompt" })
  prompt_data_json = jsonencode({
    prompt = {
      type = "chat"
      messages = [
        {
          role    = "system"
          content = "Classify the support ticket as billing, bug, or how-to. Reply with the category only."
        },
        {
          role    = "user"
          content = "{{input}}"
        },
      ]
    }
    options = { model = "gpt-5-mini" }
  })
}

resource "braintrust_function" "category_scorer" {
  project_id    = braintrust_project.support_bot.id
  name          = "Valid category"
  slug          = "valid-category"
  function_type = "scorer"

  function_data_json = jsonencode({
    type = "code"
    data = {
      type            = "inline"
      runtime_context = { runtime = "node", version = "22" }
      code            = <<-JS
        function handler({ output }) {
          const categories = ["billing", "bug", "how-to"];
          return categories.includes(String(output).trim().toLowerCase()) ? 1 : 0;
        }
      JS
    }
  })
}
```

## Use the provider in production

The example above runs from your machine with a personal API key, a local state file, and resources that don't exist yet. Managing your organization's real configuration also means planning for:

* The [credential](#authenticate-in-ci) your CI pipeline uses, and the extra requirements for [managing service tokens](#manage-service-tokens).
* Your organization's [API URL](#set-the-api-url), if it doesn't use the US data plane.
* Resources that [already exist](#import-existing-resources) in Braintrust.
* Where to [store state](#secure-the-state-file), since it holds secrets.
* How changes [roll out](#make-changes-safely) to an organization people are using.

### Authenticate in CI

The example authenticates with your personal API key. In production, run Terraform from a CI pipeline with a [service token](https://www.braintrust.dev/docs/admin/organizations.md#create-service-tokens) instead.

A service token belongs to a service account rather than a person, so pipeline runs don't depend on any one member's access. Like any credential, it can change only what its account has permission to change.

The provider accepts the token in either of two ways:

* **`BRAINTRUST_API_KEY` environment variable (recommended)**: Store the token in your CI system's secret store and expose it to Terraform as `BRAINTRUST_API_KEY`. Your configuration doesn't change.
* **`api_key` argument**: Set `api_key` in the `provider` block from a variable, never from a key written in the file. Supply the variable's value outside version control, for example with a `TF_VAR_braintrust_api_key` environment variable.

If you use the `api_key` argument, mark the variable [`sensitive`](https://developer.hashicorp.com/terraform/language/values/variables#sensitive-values-in-variables) to hide the value in Terraform's output, and `ephemeral` to keep it out of state and plan files. `ephemeral` requires Terraform 1.10 or later.

```hcl wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
variable "braintrust_api_key" {
  type      = string
  sensitive = true
  ephemeral = true
}

provider "braintrust" {
  api_key = var.braintrust_api_key
}
```

### Manage service tokens

The `braintrust_service_token` resource creates service tokens, but it requires a more privileged credential than other resources. User API keys can't create service tokens, so the resource must use a `provider` block that authenticates with a service token whose account:

* Has organization-owner permissions, or is an [owner of a project group](https://www.braintrust.dev/docs/admin/access-control/manage-permissions.md#project-group-owners).
* Holds all of the current permissions of the service account that the new token belongs to, including permissions outside any project group.

If the privileged token's account owns a project group but isn't an organization owner, the new token's service account must have access granted on that project group's projects. Access granted on an individual project in the group, or only on the project group's definition, doesn't count.

> [!TIP]
>
> To learn how service account permissions work, see [Use service accounts](https://www.braintrust.dev/docs/admin/access-control/manage-permissions.md#use-service-accounts).

The service token your pipeline uses for other resources might not have these permissions. Instead of giving it more access, give Terraform a second, more privileged credential that only your `braintrust_service_token` resources use:

1. Keep your existing `provider "braintrust"` block. It authenticates with your usual credential, and every resource uses it by default.
2. Add a second `provider "braintrust"` block with an [`alias`](https://developer.hashicorp.com/terraform/language/block/provider#alias), which names the block, and set its `api_key` to the privileged service token.
3. On each `braintrust_service_token` resource, set `provider = braintrust.<alias>` so that resource uses the second block.

```hcl wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
variable "token_admin_key" {
  description = "A service token that meets the requirements above"
  type        = string
  sensitive   = true
  ephemeral   = true
}

variable "ci_service_account_id" {
  description = "The service account the new token belongs to"
  type        = string
}

# Default credential, from BRAINTRUST_API_KEY
provider "braintrust" {}

# Second credential, used only by resources that select it
provider "braintrust" {
  alias   = "token_admin"
  api_key = var.token_admin_key
}

resource "braintrust_service_token" "ci" {
  provider           = braintrust.token_admin
  name               = "ci-pipeline"
  service_account_id = var.ci_service_account_id
}
```

### Set the API URL

The provider sends requests to `https://api.braintrust.dev` by default. If your organization uses the EU data plane or a self-hosted data plane, set `api_url` in the `provider` block or the `BRAINTRUST_API_URL` environment variable:

| Deployment | API URL |
| - | - |
| US | `https://api.braintrust.dev` (default) |
| EU | `https://api-eu.braintrust.dev` |
| Self-hosted | Your data plane's API URL |

```hcl wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
provider "braintrust" {
  api_url = "https://api-eu.braintrust.dev"
}
```

> [!TIP]
>
> You can find your organization's API URL in \*\* Settings\*\* > [\*\* Data plane\*\*](https://www.braintrust.dev/app/~/configuration/data-plane).

### Import existing resources

Importing links a resource that already exists in Braintrust, such as a project someone created in the UI, to a `resource` block in your configuration. Terraform then manages it as if it had created it: `terraform apply` updates it to match your configuration, and `terraform destroy` deletes it.

Without an import, `terraform apply` usually fails when it tries to create a resource that already exists. Environment variables and AI secrets are the exception, as [Make changes safely](#make-changes-safely) explains.

You can import every resource except `braintrust_service_account` and `braintrust_service_token`.

**1. Find the import ID**

For most resources, the import ID is the resource's Braintrust ID. These resources use a composite ID instead, made of several IDs joined by slashes:

| Resource | Import ID |
| - | - |
| `braintrust_group_membership` | `<group-id>/<user-id>` |
| `braintrust_project_group_membership` | `<project-group-id>/<project-id>` |
| `braintrust_view` | `<object-type>/<object-id>/<view-id>`, for example `project/<project-id>/<view-id>` |

**2. Import the resource**

Terraform provides two ways to import:

**Import block**

On Terraform 1.5 or later, add an [`import` block](https://developer.hashicorp.com/terraform/language/import) with the resource's ID and the `resource` block to link it to, then run `terraform apply`. The import shows up in `terraform plan` for review, like any other change.

```hcl imports.tf wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import {
  to = braintrust_project.existing
  id = "<project-id>" # Replace with the existing project's ID
}

resource "braintrust_project" "existing" {
  name = "Existing project" # Replace with the existing project's name
}
```

To have Terraform write the `resource` block for you, add only the `import` block and run `terraform plan -generate-config-out=generated.tf`. Review the generated file before you apply it.

**Import command**

On any supported Terraform version, write the `resource` block, then run `terraform import` with the block's address and the resource's ID. The command imports the resource immediately, without a plan to review.

```bash wrap theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
terraform import braintrust_project.existing <project-id>
```

### Secure the state file

Terraform records every resource it manages in a state file, including these secret values in plaintext:

* `braintrust_service_token` keys
* `braintrust_ai_secret` credentials
* `braintrust_env_var` values

Marking a value as sensitive hides it in `terraform plan` and `terraform apply` output, but doesn't keep it out of state. Store state in a [remote backend](https://developer.hashicorp.com/terraform/language/backend) that encrypts it at rest and limits who can read it. Use a backend that supports [state locking](https://developer.hashicorp.com/terraform/language/state/locking), so that two runs can't change state at the same time.

> [!WARNING]
>
> Anyone who can read the state file can read these secrets. Never commit state to version control.

### Make changes safely

Some provider behaviors affect what happens when you apply changes. For example, creating a resource that already exists usually fails, and changing an ACL removes access while Terraform replaces it. Review the following behaviors before you make changes.

> **Creating a resource that already exists fails**
>
> If a project, dataset, function, score, tag, group, project group, role, ACL, automation, view, or MCP server with the same name or slug already exists, `terraform apply` fails without changing it. [Import](#import-existing-resources) it first, or use a different name.
>
> In provider v0.0.6 and earlier, `terraform apply` takes over an existing group, role, or ACL instead of failing, and overwrites an existing function.

> **Environment variables and AI secrets overwrite existing values**
>
> If an environment variable or AI secret with the same name already exists, `terraform apply` overwrites its value instead of failing, even after an import.

> **Terraform reverts most changes made outside it**
>
> If someone edits a Terraform-managed resource in the Braintrust UI, the next `terraform apply` usually restores the configured values. Terraform can't tell when someone changes an environment variable value or AI secret credential outside Terraform, because the API never returns those values. A change made in the Braintrust UI stays in place until you change the value in your configuration and apply it.

> **Changing an ACL briefly removes access**
>
> Terraform replaces an ACL on any change, and by default it deletes the old ACL before creating the new one. If the create fails, the access stays removed until you fix the configuration and apply again. To create the new ACL first, add Terraform's [`create_before_destroy`](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#create_before_destroy) lifecycle setting to each `braintrust_acl` resource.

> **Service tokens can't be imported**
>
> A token's secret is available only when it's created. If you lose the state that holds a token, delete the token in Braintrust and create a new one.

## Next steps

* Browse the [resource and data source reference](https://registry.terraform.io/providers/braintrustdata/braintrust/latest/docs) on the Terraform Registry.
* Adapt a complete configuration, such as roles and groups for a multi-team organization or a CI pipeline with per-environment projects, from the provider's [examples](https://github.com/braintrustdata/terraform-provider-braintrust#examples).
* Follow provider releases and browse the source in the [`terraform-provider-braintrust`](https://github.com/braintrustdata/terraform-provider-braintrust) GitHub repository.
* [Control access](https://www.braintrust.dev/docs/admin/access-control.md) to learn what each permission and built-in permission group grants.
* [Manage organizations](https://www.braintrust.dev/docs/admin/organizations.md) to invite members and create API keys and service tokens.


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