---
title: "Save a connection's credentials"
method: PUT
path: "/v1/storage-connections/{id}/credentials"
tags: ["Workspaces"]
---

# Save a connection's credentials

`PUT /v1/storage-connections/{id}/credentials`

## Request

- Base URL: `https://console.nace.ai`
- URL: `https://console.nace.ai/v1/storage-connections/{id}/credentials`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/nace/apis/drex-api/docs/v1/storage-connections/:id/credentials/put.ts> (a function with typed inputs; its response is checked against the schema)

The IAM role ARN, or the Azure service principal and its secret, Nace uses to reach the destination. Write-only: they are never returned, and a refusal never quotes them. The connection has `credentials_pending` until a validation passes. Free. Only where customer storage is on for the deployment; where it is off, every storage connection route answers `404 storage_connection_unavailable` once the API key is accepted, before checking the request or its body.

## Path parameters

- `id` string, uuid, required

## Request body

- union
  - AwsRoleCredential
    - `type` 'aws_role', required
    - `role_arn` string, required: Your IAM role that trusts Nace's roles with the connection's `external_id`.
  - AzureServicePrincipalCredential
    - `type` 'azure_service_principal', required
    - `tenant_id` string, uuid, required: Your Microsoft Entra tenant.
    - `client_id` string, uuid, required: The application (client) id, with Storage Blob Data Contributor on the container.
    - `client_secret` string, required: The application's secret. Never returned.

## Response `200`

The connection, with `credentials_pending` true.

- StorageConnection
  - `id` string, uuid, required: The id a workspace create takes as `storage.connection_id`.
  - `name` string, required
  - `destination` union, required: Where a connection's workspaces keep their files. It can't change.
    - S3Destination
      - `type` 's3', required
      - `bucket` string, required: Your S3 bucket.
      - `region` string, required: The AWS region the bucket is in, such as `us-east-1`.
      - `prefix` string: A base prefix inside the bucket or container, without a leading or trailing slash. Each workspace gets its own folder beneath it.
    - AzureBlobDestination
      - `type` 'azure_blob', required
      - `account` string, required: The Azure storage account name.
      - `container` string, required: Your Blob container.
      - `prefix` string: A base prefix inside the bucket or container, without a leading or trailing slash. Each workspace gets its own folder beneath it.
  - `status` 'draft' | 'ready' | 'degraded' | 'revoked', required: `draft` until a validation passes, `ready` once Nace can use it, `degraded` when a later check failed, `revoked` once access was taken away.
  - `can_manage` boolean, required: Whether this key may change the connection: its creator's, or an owner's or admin's.
  - `external_id` string, required: The external id your IAM role's trust policy must require.
  - `aws_trusted_principal_arn` string, nullable: Older single trusted role; use `aws_trusted_principal_arns`.
  - `aws_trusted_principal_arns` string[]: Every Nace IAM role your trust policy must allow; empty for Azure.
  - `credentials_pending` boolean: Saved credentials still need a validation to pass.
  - `validation_running` boolean: A validation job is running.
  - `credential_generation` integer, required: Counts credential changes.
  - `validated_at` string, date-time, nullable: When a validation last passed.
  - `reactivation_requires_approval` boolean: Nace revoked it: only Nace support can let it be validated again.
  - `revoked_reason` 'owner' | 'administrator' | 'member_removed' | 'user_disabled' | 'null', nullable
  - `revoked_at` string, date-time, nullable
  - `created_at` string, date-time, required

## Other responses

- `401`: Missing or invalid API key (`authentication_error`, code `invalid_api_key`).
- `403`: Only the connection's creator, or an owner or admin of the account, can do this (`permission_error`, code `access_denied`).
- `404`: Customer storage is off on this deployment, which every storage connection route answers once the API key is accepted and before checking the request, or no such connection for this account (`not_found_error`, code `storage_connection_unavailable`).
- `413`: The body is over 16 KB (`invalid_request_error`, code `payload_too_large`). It is read only once the connection is found and the key may change it, so an unknown connection answers `404` and someone else's change `403` first.
- `422`: The credentials were refused (`invalid_request_error`, code `storage_credentials_refused`). Check the role ARN, or the Entra ids and secret.
- `429`: Over the account's requests per minute for document routes (`rate_limit_error`).
- `500`: Something failed on Drex's side (`internal_error`).
- `502`: The document service refused Drex's own request (`upstream_error`, code `ndi_refused_drex`). Retry later.
- `503`: The document service is unavailable (`service_unavailable`).

---

[API](https://skmtc.dev/nace/apis/drex-api.md) - [All operations](https://skmtc.dev/nace/apis/drex-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/drex-api/revisions/a0e62d925a61?raw)
