Skip to main content
Presigned feedback tokens let you collect feedback from client-side applications (browsers, mobile apps, etc.) without exposing your LangSmith 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.
If you are using 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.

Create a presigned feedback token

Use create_presigned_feedback_token() / 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:
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>

Set token expiration

Tokens expire after 3 hours by default. Pass expiration to customize this with either a timedelta (relative) or a datetime (absolute):
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),
)

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):
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,
    },
)

Create tokens in batch (Python only)

Use create_presigned_feedback_tokens (plural) to generate tokens for multiple feedback keys in a single call:
Python
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.
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.
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.
from langsmith import Client

client = Client()

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

List existing tokens

Retrieve all presigned feedback tokens for a run using list_presigned_feedback_tokens / listPresignedFeedbackTokens.
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}")