Back to Composio

True PATCH Semantics for Auth Config Updates

docs/content/changelog/01-14-26-auth-config-patch-semantics.mdx

0.11.15.5 KB
Original Source

Version Information

TypeScript/JavaScript

  • Package: @composio/core and provider packages
  • Version: 0.5.1+

Python

  • Package: composio-core and provider packages
  • Version: 0.10.7+

The PATCH /api/v3/auth_configs/{id} endpoint now implements proper partial update semantics. Previously, omitting fields would clear them (behaving like PUT). Now, omitted fields are preserved—only explicitly provided fields are modified.

<Callout type="warn"> **Breaking Change**: If you relied on omitting fields to clear them, you must now explicitly send `null` or `[]`. See [Migration Guide](#migration-guide) below. </Callout>

What Changed

FieldBefore (Buggy)After (Correct)
credentialsRequired on every updateOptional—merged with existing
tool_access_configReset to {} if omittedPreserved if omitted
scopes (type: default)Cleared if omittedPreserved if omitted
restrict_to_following_toolsReset to [] if omittedPreserved if omitted
<Callout type="info"> **Merge Behavior**: The `credentials` object is merged—send only the fields you want to change, and existing fields are preserved. </Callout>

New Capabilities

Rotate a Single Credential Field

Update just client_secret without resending client_id or other fields:

<Tabs groupId="language" items={['Python', 'TypeScript']}> <Tab value="Python">

python
from composio import Composio

composio = Composio()

# Only send the field you want to update - other credentials are preserved

composio.auth_configs.update(
    "ac_yourAuthConfigId",
    options={
        "type": "custom",
        "credentials": {
            "client_secret": "new_rotated_secret",
        },
    },
)
</Tab> <Tab value="TypeScript"> ```typescript // @noErrors import { Composio } from "@composio/core";

const composio = new Composio();

// Only send the field you want to update - other credentials are preserved await composio.authConfigs.update("ac_yourAuthConfigId", { type: "custom", credentials: { client_secret: "new_rotated_secret", }, });

</Tab>
</Tabs>

### Update Tool Restrictions Without Touching Credentials

Previously, this would fail because `credentials` was required. Now it works:

<Tabs groupId="language" items={['Python', 'TypeScript']}>
<Tab value="Python">
```python
from composio import Composio

composio = Composio()

# Update tool restrictions - credentials are automatically preserved

composio.auth_configs.update(
    "ac_yourAuthConfigId",
    options={
        "type": "custom",
        "tool_access_config": {
            "tools_available_for_execution": ["GMAIL_SEND_EMAIL", "GMAIL_READ_EMAIL"],
        },
    },
)
</Tab> <Tab value="TypeScript"> ```typescript // @noErrors import { Composio } from "@composio/core";

const composio = new Composio();

// Note: TypeScript SDK currently requires credentials for custom type updates await composio.authConfigs.update("ac_yourAuthConfigId", { type: "custom", credentials: { // Include existing credentials when using TS SDK }, toolAccessConfig: { toolsAvailableForExecution: ["GMAIL_SEND_EMAIL", "GMAIL_READ_EMAIL"], }, });

</Tab>
</Tabs>

## Migration Guide

### Am I Affected?

**Yes**, if your code relied on omitting fields to clear them.

**No**, if you always send complete payloads or only use PATCH to update specific fields.

### How to Clear Fields Explicitly

| To Clear             | Python SDK                                                    | TypeScript SDK                                         |
| -------------------- | ------------------------------------------------------------- | ------------------------------------------------------ |
| `tool_access_config` | `"tool_access_config": {"tools_available_for_execution": []}` | `toolAccessConfig: { toolsAvailableForExecution: [] }` |
| `scopes` (default)   | `"scopes": ""`                                                | `scopes: ""` (via HTTP API)                            |

<Tabs groupId="language" items={['Python', 'TypeScript']}>
<Tab value="Python">
```python
from composio import Composio

composio = Composio()

# Explicitly clear tool restrictions with empty array

composio.auth_configs.update(
    "ac_yourAuthConfigId",
    options={
        "type": "custom",
        "tool_access_config": {
            "tools_available_for_execution": [],
        },
    },
)
</Tab> <Tab value="TypeScript"> ```typescript // @noErrors import { Composio } from "@composio/core";

const composio = new Composio();

// Explicitly clear tool restrictions with empty array await composio.authConfigs.update("ac_yourAuthConfigId", { type: "custom", credentials: { // Include existing credentials when using TS SDK }, toolAccessConfig: { toolsAvailableForExecution: [], }, });

</Tab>
</Tabs>

### Raw HTTP API

For users calling the API directly:

```bash
# Rotate single credential
curl -X PATCH "https://backend.composio.dev/api/v3/auth_configs/{id}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "custom", "credentials": {"client_secret": "new_secret"}}'

# Clear tool restrictions
curl -X PATCH "https://backend.composio.dev/api/v3/auth_configs/{id}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "custom", "tool_access_config": {"tools_available_for_execution": []}}'