---
title: "Set or rotate this org’s OAuth app for a connector"
method: PUT
path: "/connector/{slug}/oauth-app"
tags: ["Connectors"]
---

# Set or rotate this org’s OAuth app for a connector

`PUT /connector/{slug}/oauth-app`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/connector/{slug}/oauth-app`
- Auth: HTTP bearer

Replaces the stored application wholesale, with one exception the setup form depends on: omitting `client_secret` keeps the secret already stored, so correcting a typo in the client id cannot destroy a working secret. Send both to rotate. Scope overrides (`scope`, `optional_scope`, `user_scope`) are optional; omit them to keep the connector’s catalog scopes, or send arrays to replace them. Endpoint fields (token host, other authorize params) are not accepted here by design. Returns the same shape as the read, so the secret does not come back. Requires `connector:manage`.

## Path parameters

- `slug` string, required

## Headers

- `X-Organization-Id` string

## Request body

- object
  - `client_id` string, required
  - `client_secret` string: Omit to keep the stored secret. Never returned by any endpoint.
  - `scope` string[]: Omit to keep the catalog scopes; an array overrides them wholesale.
  - `optional_scope` string[]
  - `user_scope` string: Authorize-URL scopes (`params.user_scope`), separated by spaces or commas and stored space-separated. Only where `supports_user_scope` is true; omit to clear.

## Response `200`

OK

- object
  - `oauth_app_mode` 'platform_default' | 'byoa': Which application connects on this connector use.
  - `client_id` string, nullable
  - `has_client_secret` boolean: Whether a secret is stored. The secret itself is never returned.
  - `scope` string[], nullable: Scope overrides this org stored, or null when it kept the catalog scopes.
  - `optional_scope` string[], nullable
  - `user_scope` string, nullable: Space-separated authorize-URL scopes (`params.user_scope`), or null. Null also when one is stored but held back, see `user_scope_masked`.
  - `user_scope_masked` boolean: True when a `user_scope` is stored encrypted by an older write and cannot be read or changed here. A `PUT` that sets `user_scope` then answers `409`.
  - `supports_user_scope` boolean: Whether this connector’s provider takes user token scopes (Slack does). Where false, a `user_scope` that differs from the stored one is refused with `400`.
  - `updated_at` string, nullable

## Other responses

- `400`: Bad request. Includes a `user_scope` with a token that is not a scope (`validation_error`), and a `user_scope` that differs from the stored one on a connector that takes none (`user_scope_unsupported`).
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `409`: The stored `user_scope` is held encrypted by an older write and cannot be changed here (`user_scope_masked`). Remove the OAuth application and add it again to replace it.
- `429`: Rate limited

---

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