> ## Documentation Index
> Fetch the complete documentation index at: https://docs.langchain.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Collect feedback with presigned URLs

> Use presigned feedback tokens to collect user feedback from client-side applications without exposing your LangSmith API key.

Presigned feedback tokens let you collect [feedback](/langsmith/observability-concepts#feedback) from client-side applications (browsers, mobile apps, etc.) without exposing your [LangSmith API key](/langsmith/create-account-api-key). Each token generates a URL scoped to a specific run and feedback key. Clients submit feedback by calling that URL directly with no authentication required.

This is useful when:

* Your frontend collects thumbs up/down or star ratings from end users.
* You want to embed feedback links in emails, Slack messages, or other external channels.
* You need to decouple feedback collection from your backend.

<Note>
  If you are using [Agent Server](/langsmith/agent-server), presigned feedback URLs are generated automatically when you include `feedback_keys` in the run request. For that workflow, refer to [Collect user feedback for Agent Server runs](/langsmith/agent-server-feedback).
</Note>

## Create a presigned feedback token

Use [`create_presigned_feedback_token()`](https://reference.langchain.com/python/langsmith/client/Client/create_presigned_feedback_token) / [`createPresignedFeedbackToken`](https://reference.langchain.com/javascript/classes/langsmith.client.Client.html#createpresignedfeedbacktoken) to generate a token for a specific run and feedback key. The returned object includes a `url` that clients can call to submit feedback:

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  from langsmith import Client

  client = Client()

  run_id = "<run_id>"

  token = client.create_presigned_feedback_token(
      run_id,
      feedback_key="user_score",
  )

  print(token.url)
  # https://api.smith.langchain.com/api/v1/feedback/tokens/<token_id>
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import { Client } from "langsmith";

  const client = new Client();

  const runId = "<run_id>";

  const token = await client.createPresignedFeedbackToken(runId, "user_score");

  console.log(token.url);
  // https://api.smith.langchain.com/api/v1/feedback/tokens/<token_id>
  ```
</CodeGroup>

### Set token expiration

Tokens expire after 3 hours by default. Pass `expiration` to customize this with either a `timedelta` (relative) or a `datetime` (absolute):

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import datetime
  from langsmith import Client

  client = Client()

  run_id = "<run_id>"

  token = client.create_presigned_feedback_token(
      run_id,
      feedback_key="user_score",
      expiration=datetime.timedelta(hours=24),
  )
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import { Client } from "langsmith";

  const client = new Client();

  const runId = "<run_id>";

  const token = await client.createPresignedFeedbackToken(runId, "user_score", {
    expiration: { hours: 24 },
  });
  ```
</CodeGroup>

### Constrain feedback values

Pass `feedback_config` to restrict what values clients can submit. This is useful for enforcing a specific feedback schema (e.g., thumbs up/down, 1–5 stars, or categorical labels):

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  from langsmith import Client

  client = Client()

  run_id = "<run_id>"

  token = client.create_presigned_feedback_token(
      run_id,
      feedback_key="user_score",
      feedback_config={
          "type": "continuous",
          "min": 0,
          "max": 1,
      },
  )
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import { Client } from "langsmith";

  const client = new Client();

  const runId = "<run_id>";

  const token = await client.createPresignedFeedbackToken(runId, "user_score", {
    feedbackConfig: {
      type: "continuous",
      min: 0,
      max: 1,
    },
  });
  ```
</CodeGroup>

### Create tokens in batch (Python only)

Use `create_presigned_feedback_tokens` (plural) to generate tokens for multiple feedback keys in a single call:

```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from langsmith import Client

client = Client()

run_id = "<run_id>"

tokens = client.create_presigned_feedback_tokens(
    run_id,
    feedback_keys=["thumbs_up", "thumbs_down"],
)

for token in tokens:
    print(f"{token.id}: {token.url}")
```

## Submit feedback with a presigned URL

Once you have a presigned URL, your frontend code or email client submits feedback by sending a `POST` or `GET` request to it. The URL does not require an API key or authentication because the token provides the authorization.

### POST request

Use `POST` from your frontend when a user interacts with a feedback control (e.g., clicking a thumbs up button). `POST` supports `score`, `value`, `comment`, `correction`, and `metadata` fields.

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
curl --request POST \
  --url "https://api.smith.langchain.com/api/v1/feedback/tokens/<token_id>" \
  --header "Content-Type: application/json" \
  --data '{
    "score": 1,
    "comment": "This response was helpful!"
  }'
```

### GET request

Use `GET` when embedding a feedback link in an email or Slack message. The user's click triggers the request. `GET` supports `score`, `value`, `comment`, and `correction` as query parameters. `metadata` is not supported with `GET`.

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
curl --request GET \
  --url "https://api.smith.langchain.com/api/v1/feedback/tokens/<token_id>?score=1&comment=This%20response%20was%20helpful!"
```

### Submit feedback using the SDK

You can also submit feedback from a presigned token using the SDK, which is useful for server-side workflows where you received a token URL from another service.

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  from langsmith import Client

  client = Client()

  client.create_feedback_from_token(
      "<token_or_url>",
      score=1,
      comment="This response was helpful!",
  )
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  // Use a direct HTTP request to the presigned URL
  await fetch(tokenUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      score: 1,
      comment: "This response was helpful!",
    }),
  });
  ```
</CodeGroup>

## List existing tokens

Retrieve all presigned feedback tokens for a run using `list_presigned_feedback_tokens` / `listPresignedFeedbackTokens`.

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  from langsmith import Client

  client = Client()

  run_id = "<run_id>"

  for token in client.list_presigned_feedback_tokens(run_id):
      print(f"ID: {token.id}, URL: {token.url}, Expires: {token.expires_at}")
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import { Client } from "langsmith";

  const client = new Client();

  const runId = "<run_id>";

  for await (const token of client.listPresignedFeedbackTokens(runId)) {
    console.log(`URL: ${token.url}, Expires: ${token.expires_at}`);
  }
  ```
</CodeGroup>

## Related

* [Reference guide on feedback data format](/langsmith/feedback-data-format)
* [Log feedback using the SDK](/langsmith/attach-user-feedback)

***

<div className="source-links">
  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>

  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/presigned-feedback-tokens.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>
</div>
