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

# Update Credentials

> Add or update credentials for a server in your stack

## Overview

Updates the credentials for a specific server in your stack. This endpoint allows you to add new credentials or update existing ones. All credentials are encrypted and securely stored.

<Warning>
  Credentials are sensitive data. Ensure you're using secure connections and keep your API keys safe.
</Warning>

## Endpoint

```
PUT https://api.toolrouter.ai/v1/stacks/{stack_id}/servers/{server_id}/credentials
```

## Authentication

This endpoint requires an API key. Include it in the Authorization header:

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

## Path Parameters

<ParamField path="stack_id" type="string" required>
  The unique identifier of the stack containing the server
</ParamField>

<ParamField path="server_id" type="string" required>
  The unique identifier of the server to update credentials for
</ParamField>

## Request Body

<ParamField body="credentials" type="object" required>
  Object containing credential field IDs as keys and their values as values

  <Expandable title="Credential Fields">
    The keys should match the credential field IDs from the server definition. You can find these using the [List Servers](/api-reference/endpoint/account/list_servers) endpoint.

    Example credential fields:

    * `gmail_oauth_token`: OAuth token for Gmail API
    * `gmail_client_id`: Client ID for Gmail OAuth
    * `gmail_client_secret`: Client secret for Gmail OAuth
    * `linear_api_key`: API key for Linear integration
  </Expandable>
</ParamField>

## Response

<ResponseField name="message" type="string">
  Confirmation message indicating credentials were updated successfully
</ResponseField>

## Example Request

### Configure Gmail Credentials

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/gmail/credentials" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "credentials": {
        "gmail_oauth_token": "ya29.a0AfH6SMC...",
        "gmail_client_id": "123456789-abcdef.apps.googleusercontent.com",
        "gmail_client_secret": "GOCSPX-abc123def456",
        "gmail_signature": "Best regards,\nJohn Doe"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  data = {
      "credentials": {
          "gmail_oauth_token": "ya29.a0AfH6SMC...",
          "gmail_client_id": "123456789-abcdef.apps.googleusercontent.com", 
          "gmail_client_secret": "GOCSPX-abc123def456",
          "gmail_signature": "Best regards,\nJohn Doe"
      }
  }

  response = requests.put(
      "https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/gmail/credentials",
      headers=headers,
      json=data
  )

  result = response.json()
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/gmail/credentials', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      credentials: {
        gmail_oauth_token: "ya29.a0AfH6SMC...",
        gmail_client_id: "123456789-abcdef.apps.googleusercontent.com",
        gmail_client_secret: "GOCSPX-abc123def456",
        gmail_signature: "Best regards,\nJohn Doe"
      }
    })
  });

  const result = await response.json();
  ```
</CodeGroup>

### Configure Linear Credentials

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/linear/credentials" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "credentials": {
        "linear_api_key": "lin_api_abc123def456789"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  data = {
      "credentials": {
          "linear_api_key": "lin_api_abc123def456789"
      }
  }

  response = requests.put(
      "https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/linear/credentials",
      headers=headers,
      json=data
  )

  result = response.json()
  ```
</CodeGroup>

### Update Specific Credentials

<CodeGroup>
  ```bash cURL theme={null}
  # Update only the OAuth token, leaving other credentials unchanged
  curl -X PUT "https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/gmail/credentials" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "credentials": {
        "gmail_oauth_token": "ya29.a0AfH6SMC_new_token..."
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  # Update only specific credentials
  data = {
      "credentials": {
          "gmail_oauth_token": "ya29.a0AfH6SMC_new_token..."
      }
  }

  response = requests.put(
      "https://api.toolrouter.ai/v1/stacks/stack_123e4567-e89b-12d3-a456-426614174000/servers/gmail/credentials",
      headers=headers,
      json=data
  )

  result = response.json()
  ```
</CodeGroup>

## Example Response

```json theme={null}
{
  "message": "Credentials updated successfully"
}
```

## Security Features

### Encryption

* All credentials are encrypted using industry-standard encryption before storage
* Credentials are never stored in plain text
* Encryption keys are managed separately from the stored credentials

### Access Control

* Credentials are isolated per user and stack
* Only the stack owner can view or modify credentials
* API key authentication ensures secure access

### Audit Trail

* All credential updates are logged for security monitoring
* Changes can be tracked for compliance requirements

## Credential Management Best Practices

### Secure Handling

```python theme={null}
import os
import requests

# Use environment variables for sensitive data
headers = {
    "Authorization": f"Bearer {os.getenv('TOOLROUTER_API_KEY')}",
    "Content-Type": "application/json"
}

data = {
    "credentials": {
        "gmail_oauth_token": os.getenv('GMAIL_OAUTH_TOKEN'),
        "gmail_client_secret": os.getenv('GMAIL_CLIENT_SECRET')
    }
}

# Never log or print credential values
response = requests.put(endpoint_url, headers=headers, json=data)
```

### Regular Rotation

* Rotate credentials periodically for security
* Update credentials immediately if they may have been compromised
* Use this endpoint to update credentials when they expire

### Validation

After updating credentials, verify they work:

```python theme={null}
# Update credentials
update_response = requests.put(credentials_endpoint, headers=headers, json=credential_data)

# Check status
status_response = requests.get(f"https://api.toolrouter.ai/v1/stacks/{stack_id}/servers/{server_id}/credentials", headers=headers)
status = status_response.json()

# Test with a simple tool call
if status["required_credentials_added"]:
    # Try invoking a tool to verify credentials work
    tool_response = requests.post(f"https://api.toolrouter.ai/v1/stacks/{stack_id}/tools/{tool_id}/invoke", 
                                headers=headers, json=test_input)
```

## Error Responses

<ResponseField name="400 Bad Request">
  Invalid credential data or format

  ```json theme={null}
  {
    "detail": "Invalid credential format"
  }
  ```
</ResponseField>

<ResponseField name="401 Unauthorized">
  Invalid or missing API key

  ```json theme={null}
  {
    "detail": "Unauthorized"
  }
  ```
</ResponseField>

<ResponseField name="404 Not Found">
  Stack, server, or server not found in stack

  ```json theme={null}
  {
    "detail": "Stack not found"
  }
  ```

  ```json theme={null}
  {
    "detail": "Server gmail not found"
  }
  ```
</ResponseField>

<ResponseField name="429 Too Many Requests">
  Rate limit exceeded

  ```json theme={null}
  {
    "detail": "Too many requests"
  }
  ```
</ResponseField>

<ResponseField name="500 Internal Server Error">
  Server error occurred

  ```json theme={null}
  {
    "detail": "Failed to update credentials"
  }
  ```
</ResponseField>

## Next Steps

After updating credentials:

1. **Verify status**: Use [Get Credentials Status](/api-reference/endpoint/account/get_credentials_status) to confirm all required credentials are added
2. **Test functionality**: Use [Invoke Tool](/api-reference/endpoint/account/invoke_tool) to verify tools work with the new credentials
3. **Monitor usage**: Check that your applications can successfully use the tools with the updated credentials
