OAuth Apps

Create OAuth app

Changed on

Register a new OAuth app for the organization. Any authenticated org member may create apps; the creator is recorded as the app's owner and is the only user who can subsequently read, update, suspend, activate, regenerate the secret of, or delete it.

The clientSecret is returned in this response only — it is stored hashed server-side and cannot be retrieved later. Persist it before exiting the create flow; if it is ever lost, rotate via POST /oauth-clients/{appId}/regenerate-secret.

allowedScopes is validated against the caller's role-aware scope set (see GET /oauth-clients/scopes). Org admins may include admin-only scopes; non-admins requesting a restricted scope receive 400.

All /oauth-clients/* routes share a per-user rate limiter (default 1000 req/min, configurable via the MAX_OAUTH_CLIENT_REQUESTS_PER_MINUTE env var).

post/oauth-clients

Request

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

Request body

namestring required

App name (displayed to users during authorization)

tokenIdentityUserIdstring

The service account this app's own tokens act as. Required when allowedGrantTypes includes client_credentials, ignored otherwise.

Must name a service account in the same organisation that is not disabled; an ordinary user's id is refused. Administrators only.

descriptionstring

App description

redirectUrisstring[]

Allowed redirect URIs (max 10). Required when an effective grant list includes authorization_code (including the default when allowedGrantTypes is omitted). 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[]

Allowed grant types. Defaults to ["authorization_code", "refresh_token"] if omitted (applied by the service, not Zod).

allowedScopesstring[] required

Scopes the app can request (non-empty)

homepageUrlstring uri

App homepage URL (shown during authorization). Must parse as a URL (z.string().url()); the pattern is the closest JSON Schema can say.

privacyPolicyUrlstring uri

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

termsOfServiceUrlstring uri

Terms of service URL. Must parse as a URL (z.string().url()); the pattern is the closest JSON Schema can say.

isConfidentialboolean

Whether the app can securely store secrets.

  • true: Server-side app (secret required for token requests)
  • false: Browser/mobile app (must use PKCE)
accessTokenLifetimeinteger

Access token lifetime in seconds (300–86400)

refreshTokenLifetimeinteger

Refresh token lifetime in seconds (3600–31536000)

Example request

{
  "name": "My Integration App",
  "tokenIdentityUserId": "65f0c0ffee00000000000000",
  "description": "Integrates PipesHub with our internal tools",
  "redirectUris": [
    "https://myapp.com/callback",
    "http://localhost:3000/callback"
  ],
  "allowedGrantTypes": [
    "authorization_code",
    "refresh_token"
  ],
  "allowedScopes": [
    "openid",
    "profile",
    "read:records"
  ],
  "accessTokenLifetime": 3600,
  "refreshTokenLifetime": 2592000
}

Response

OAuth app created successfully

messagestring required

Example response

{
  "message": "OAuth app created 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

      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 new optional request property

    • 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