OAuth Apps

Update OAuth app

Changed on

Update an OAuth app's configuration. All body fields are optional — supply only what should change. URL fields (homepageUrl, privacyPolicyUrl, termsOfServiceUrl) accept null to clear them.

Adding client_credentials to allowedGrantTypes requires an organisation administrator, because it settles whose documents the application's tokens reach. A non-administrator answers 403, and that check runs first — so a member sees 403 whether or not a service account is bound.

For an administrator, it answers 400 when no service account is bound or the bound account is disabled, and 404 when the bound identity no longer exists or is not a service account — distinct from the 404 for an application this caller cannot see. Point the application at one first with PUT /oauth-clients/{appId}/token-identity. An application that already allows the grant without a service account predates this rule and can still be edited.

Creator-only: even org admins cannot edit apps owned by other users.

When modifying allowedScopes, the new set must remain a subset of the caller's role-aware scope list (same rule as GET /oauth-clients/scopes). The Zod refine on updateAppSchema only looks at the body: it refuses allowedGrantTypes containing authorization_code together with an empty redirectUris (400 VALIDATION_ERROR), but sending authorization_code without redirectUris is accepted even when the stored app has no redirect URI.

This endpoint never rotates the client secret — use POST /oauth-clients/{appId}/regenerate-secret for that.

put/oauth-clients/{appId}

Request

  • Base URL
    https://app.pipeshub.com/api/v1
  • URL
    https://app.pipeshub.com/api/v1/oauth-clients/{appId}
  • Auth
    HTTP bearer

Path parameters

appIdstring required

OAuth app ID

Request body

namestring

App name

descriptionstring

App description

redirectUrisstring[]

Allowed redirect URIs (up to 10). Required when authorization_code grant type is enabled. Preserved in the database even if authorization_code is removed from grant types. Each URI must parse as a URL (VALIDATION_ERROR otherwise), and the service then refuses with 400 OAUTH_INVALID_REDIRECT_URI any URI that is not https: and whose host is not localhost or 127.0.0.1 (any scheme is let through on those two hosts), or that carries a fragment. The one exception is the literal cursor://anysphere.cursor-mcp/oauth/callback. Both checks use WHATWG new URL(), so the scheme and a localhost host match in any case, https: may be followed by any number of / or \ (or none), and surrounding whitespace is allowed and trimmed before the URI is stored; the URI is otherwise stored as sent. https:// with no host does not parse. The pattern approximates these rules.

allowedGrantTypesstring[]
allowedScopesstring[]
homepageUrlstring uri nullable

null clears it. Must parse as a URL (z.string().url()); the pattern is the closest JSON Schema can say.

privacyPolicyUrlstring uri nullable

null clears it. Must parse as a URL (z.string().url()); the pattern is the closest JSON Schema can say.

termsOfServiceUrlstring uri nullable

null clears it. Must parse as a URL (z.string().url()); the pattern is the closest JSON Schema can say.

accessTokenLifetimeinteger
refreshTokenLifetimeinteger

Response

OAuth app updated

messagestring required

Example response

{
  "message": "OAuth app updated successfully",
  "app": {
    "tokenIdentityUserId": "65f0c0ffee00000000000000"
  }
}

Changes

    • breaking

      added the pattern ^(?:cursor://anysphere\.cursor-mcp/oauth/callback|[\x00-\x20]*(?:[Hh][Tt][Tt][Pp][Ss]:[/\\]*[^/\\?#\x00-\x20][^#]*#?|[A-Za-z][A-Za-z0-9+.-]*://(?:[^/?#@]*@)?(?:[Ll][Oo][Cc][Aa][Ll][Hh][Oo][Ss][Tt]|127\.0\.0\.1)(?::[0-9]*)?(?:[/?][^#]*)?#?)[\x00-\x20]*)$ to the request property /

    • breaking

      added the pattern ^[A-Za-z][A-Za-z0-9+.-]*: to the request property

    • breaking

      added the pattern ^[A-Za-z][A-Za-z0-9+.-]*: to the request property

    • breaking

      added the pattern ^[A-Za-z][A-Za-z0-9+.-]*: to the request property

    • info

      request body became optional

    • info

      added the non-success response with the status

    • info

      added the non-success response with the status

    • info

      added the optional property / to the response with the status

    • info

      added the optional property / to the response with the status

    • info

      added the optional property / to the response with the status

    • info

      added the optional property / to the response with the status

    • info

      added the new optional request property

    • info

      added the optional property / to the response with the status

    • info

      added the optional property / to the response with the status