---
title: "Pin conversation"
method: PATCH
path: "/conversations/{conversationId}/pin"
tags: ["Conversations"]
---

# Pin conversation

`PATCH /conversations/{conversationId}/pin`

## Request

- Base URL: `https://app.pipeshub.com/api/v1`
- URL: `https://app.pipeshub.com/api/v1/conversations/{conversationId}/pin`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `/api/v1/oauth2/authorize`
    - Client credentials
    - Token URL: `/api/v1/oauth2/token` scopes: `conversation:write`

Pin a conversation so it is listed first in the caller's own conversation list.

**Access:**

Owner only: the caller must be the conversation's `initiator`. People the
conversation is shared with, even with `write` access, cannot pin it, and
their own lists are not affected by the owner's pin.

**Behaviour:**

Idempotent: pinning an already pinned conversation succeeds and changes nothing.
Archived and deleted conversations cannot be pinned. Archiving a pinned
conversation removes its pin. Pinning does not change `lastActivityAt` or
`updatedAt`, so the conversation keeps its place among the other pinned chats.

- Path params: `conversationId`
- Query params: none
- Body: none

## Path parameters

- `conversationId` string, objectId, required

## Response `200`

Conversation is pinned

- ConversationPinResponse
  - `id` string, objectId, required: Conversation identifier
  - `isPinned` boolean, required: The conversation's pin state after the call.
  - `meta` object, required
    - `requestId` string: Request correlation identifier
    - `timestamp` string, date-time: Response generation timestamp
    - `duration` integer: Server processing time in milliseconds

## Other responses

- `400`: Missing user or organization context, or `conversationId` is not a valid id (`VALIDATION_ERROR`). Also returned, before authentication, when a query value, or any string in a JSON or form-encoded body, looks like markup to the app-wide XSS filter: an HTML tag, a script tag, `<iframe`, `<object`, `<embed` or `<svg` tag, a word starting with `on` followed by `=` (meant for inline event handlers such as `onerror=`, it also catches plain text such as `one=1`), a `javascript:` or `data:text/html` URL, an encoded script tag (`&lt;script`, `%3cscript`), or any string longer than 100,000 characters (`HTTP_BAD_REQUEST`, "HTML tags, scripts, and XSS content are not allowed in ...", naming the field or query parameter; a string over 100,000 characters is refused as too long instead). A JSON body that does not parse is refused the same way, also before authentication (`HTTP_BAD_REQUEST`, "The request body is not valid JSON.").
- `401`: Unauthorized
- `403`: Forbidden - token is missing the `conversation:write` scope
- `404`: Conversation not found, deleted, archived, an agent conversation, or not owned by the caller (`Conversation not found or not owned by caller`).
- `500`: Persistence layer failed to update the conversation document. A JSON body larger than 10 MB, or a form-encoded body larger than 100 KB or with more than 1000 fields, is answered `413` by the app-wide body parsers instead, also before authentication.

## Changes

- **2026-10-28** `dbb5e203b445`: 5 info
  - added the media type `application/json` for the response with the status `400`
  - added the media type `application/json` for the response with the status `401`
  - added the media type `application/json` for the response with the status `403`
  - added the media type `application/json` for the response with the status `404`
  - …1 more
- **2026-10-21** `a90ab79f26a1`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/pipeshub-ai/apis/pipeshub-api/changes/conversations/:conversationId/pin/patch.md)

---

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