curl --request POST \
--url https://api.usenotra.com/v1/feedback/{organizationSlug} \
--header 'Content-Type: application/json' \
--data '
{
"message": "The search tool times out when the query has quotes.",
"title": "Search times out on quoted queries",
"kind": "bug",
"sentiment": "negative",
"source": "mcp",
"projectId": "<string>",
"agentClient": "claude-code",
"agentModel": "claude-opus-5",
"toolVersion": "1.2.0",
"userAgent": "<string>",
"contextUrl": "https://docs.example.com/api/search",
"externalId": "<string>",
"idempotencyKey": "<string>",
"metadata": {}
}
'import requests
url = "https://api.usenotra.com/v1/feedback/{organizationSlug}"
payload = {
"message": "The search tool times out when the query has quotes.",
"title": "Search times out on quoted queries",
"kind": "bug",
"sentiment": "negative",
"source": "mcp",
"projectId": "<string>",
"agentClient": "claude-code",
"agentModel": "claude-opus-5",
"toolVersion": "1.2.0",
"userAgent": "<string>",
"contextUrl": "https://docs.example.com/api/search",
"externalId": "<string>",
"idempotencyKey": "<string>",
"metadata": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
message: 'The search tool times out when the query has quotes.',
title: 'Search times out on quoted queries',
kind: 'bug',
sentiment: 'negative',
source: 'mcp',
projectId: '<string>',
agentClient: 'claude-code',
agentModel: 'claude-opus-5',
toolVersion: '1.2.0',
userAgent: '<string>',
contextUrl: 'https://docs.example.com/api/search',
externalId: '<string>',
idempotencyKey: '<string>',
metadata: {}
})
};
fetch('https://api.usenotra.com/v1/feedback/{organizationSlug}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.usenotra.com/v1/feedback/{organizationSlug}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'message' => 'The search tool times out when the query has quotes.',
'title' => 'Search times out on quoted queries',
'kind' => 'bug',
'sentiment' => 'negative',
'source' => 'mcp',
'projectId' => '<string>',
'agentClient' => 'claude-code',
'agentModel' => 'claude-opus-5',
'toolVersion' => '1.2.0',
'userAgent' => '<string>',
'contextUrl' => 'https://docs.example.com/api/search',
'externalId' => '<string>',
'idempotencyKey' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.usenotra.com/v1/feedback/{organizationSlug}"
payload := strings.NewReader("{\n \"message\": \"The search tool times out when the query has quotes.\",\n \"title\": \"Search times out on quoted queries\",\n \"kind\": \"bug\",\n \"sentiment\": \"negative\",\n \"source\": \"mcp\",\n \"projectId\": \"<string>\",\n \"agentClient\": \"claude-code\",\n \"agentModel\": \"claude-opus-5\",\n \"toolVersion\": \"1.2.0\",\n \"userAgent\": \"<string>\",\n \"contextUrl\": \"https://docs.example.com/api/search\",\n \"externalId\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.usenotra.com/v1/feedback/{organizationSlug}")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"The search tool times out when the query has quotes.\",\n \"title\": \"Search times out on quoted queries\",\n \"kind\": \"bug\",\n \"sentiment\": \"negative\",\n \"source\": \"mcp\",\n \"projectId\": \"<string>\",\n \"agentClient\": \"claude-code\",\n \"agentModel\": \"claude-opus-5\",\n \"toolVersion\": \"1.2.0\",\n \"userAgent\": \"<string>\",\n \"contextUrl\": \"https://docs.example.com/api/search\",\n \"externalId\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usenotra.com/v1/feedback/{organizationSlug}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"message\": \"The search tool times out when the query has quotes.\",\n \"title\": \"Search times out on quoted queries\",\n \"kind\": \"bug\",\n \"sentiment\": \"negative\",\n \"source\": \"mcp\",\n \"projectId\": \"<string>\",\n \"agentClient\": \"claude-code\",\n \"agentModel\": \"claude-opus-5\",\n \"toolVersion\": \"1.2.0\",\n \"userAgent\": \"<string>\",\n \"contextUrl\": \"https://docs.example.com/api/search\",\n \"externalId\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"feedback": {
"id": "<string>",
"projectId": "<string>",
"source": "mcp",
"kind": "bug",
"sentiment": "negative",
"status": "new",
"title": "<string>",
"message": "<string>",
"agentClient": "<string>",
"agentModel": "<string>",
"toolVersion": "<string>",
"userAgent": "<string>",
"contextUrl": "<string>",
"externalId": "<string>",
"idempotencyKey": "<string>",
"metadata": {},
"resolvedAt": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>"
},
"deduplicated": true
}{
"error": "<string>",
"code": "<string>",
"recovery": "<string>"
}{
"error": "<string>",
"code": "<string>",
"recovery": "<string>"
}{
"error": "<string>",
"limit": 2,
"remaining": 1,
"reset": 123
}Submit feedback to an organization's feedback URL
Record feedback from an AI agent or integration by posting to the organization’s feedback URL, as shown on the Feedback page in the dashboard. No credentials are required. Limited per source IP and per organization.
curl --request POST \
--url https://api.usenotra.com/v1/feedback/{organizationSlug} \
--header 'Content-Type: application/json' \
--data '
{
"message": "The search tool times out when the query has quotes.",
"title": "Search times out on quoted queries",
"kind": "bug",
"sentiment": "negative",
"source": "mcp",
"projectId": "<string>",
"agentClient": "claude-code",
"agentModel": "claude-opus-5",
"toolVersion": "1.2.0",
"userAgent": "<string>",
"contextUrl": "https://docs.example.com/api/search",
"externalId": "<string>",
"idempotencyKey": "<string>",
"metadata": {}
}
'import requests
url = "https://api.usenotra.com/v1/feedback/{organizationSlug}"
payload = {
"message": "The search tool times out when the query has quotes.",
"title": "Search times out on quoted queries",
"kind": "bug",
"sentiment": "negative",
"source": "mcp",
"projectId": "<string>",
"agentClient": "claude-code",
"agentModel": "claude-opus-5",
"toolVersion": "1.2.0",
"userAgent": "<string>",
"contextUrl": "https://docs.example.com/api/search",
"externalId": "<string>",
"idempotencyKey": "<string>",
"metadata": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
message: 'The search tool times out when the query has quotes.',
title: 'Search times out on quoted queries',
kind: 'bug',
sentiment: 'negative',
source: 'mcp',
projectId: '<string>',
agentClient: 'claude-code',
agentModel: 'claude-opus-5',
toolVersion: '1.2.0',
userAgent: '<string>',
contextUrl: 'https://docs.example.com/api/search',
externalId: '<string>',
idempotencyKey: '<string>',
metadata: {}
})
};
fetch('https://api.usenotra.com/v1/feedback/{organizationSlug}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.usenotra.com/v1/feedback/{organizationSlug}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'message' => 'The search tool times out when the query has quotes.',
'title' => 'Search times out on quoted queries',
'kind' => 'bug',
'sentiment' => 'negative',
'source' => 'mcp',
'projectId' => '<string>',
'agentClient' => 'claude-code',
'agentModel' => 'claude-opus-5',
'toolVersion' => '1.2.0',
'userAgent' => '<string>',
'contextUrl' => 'https://docs.example.com/api/search',
'externalId' => '<string>',
'idempotencyKey' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.usenotra.com/v1/feedback/{organizationSlug}"
payload := strings.NewReader("{\n \"message\": \"The search tool times out when the query has quotes.\",\n \"title\": \"Search times out on quoted queries\",\n \"kind\": \"bug\",\n \"sentiment\": \"negative\",\n \"source\": \"mcp\",\n \"projectId\": \"<string>\",\n \"agentClient\": \"claude-code\",\n \"agentModel\": \"claude-opus-5\",\n \"toolVersion\": \"1.2.0\",\n \"userAgent\": \"<string>\",\n \"contextUrl\": \"https://docs.example.com/api/search\",\n \"externalId\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.usenotra.com/v1/feedback/{organizationSlug}")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"The search tool times out when the query has quotes.\",\n \"title\": \"Search times out on quoted queries\",\n \"kind\": \"bug\",\n \"sentiment\": \"negative\",\n \"source\": \"mcp\",\n \"projectId\": \"<string>\",\n \"agentClient\": \"claude-code\",\n \"agentModel\": \"claude-opus-5\",\n \"toolVersion\": \"1.2.0\",\n \"userAgent\": \"<string>\",\n \"contextUrl\": \"https://docs.example.com/api/search\",\n \"externalId\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usenotra.com/v1/feedback/{organizationSlug}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"message\": \"The search tool times out when the query has quotes.\",\n \"title\": \"Search times out on quoted queries\",\n \"kind\": \"bug\",\n \"sentiment\": \"negative\",\n \"source\": \"mcp\",\n \"projectId\": \"<string>\",\n \"agentClient\": \"claude-code\",\n \"agentModel\": \"claude-opus-5\",\n \"toolVersion\": \"1.2.0\",\n \"userAgent\": \"<string>\",\n \"contextUrl\": \"https://docs.example.com/api/search\",\n \"externalId\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"feedback": {
"id": "<string>",
"projectId": "<string>",
"source": "mcp",
"kind": "bug",
"sentiment": "negative",
"status": "new",
"title": "<string>",
"message": "<string>",
"agentClient": "<string>",
"agentModel": "<string>",
"toolVersion": "<string>",
"userAgent": "<string>",
"contextUrl": "<string>",
"externalId": "<string>",
"idempotencyKey": "<string>",
"metadata": {},
"resolvedAt": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>"
},
"deduplicated": true
}{
"error": "<string>",
"code": "<string>",
"recovery": "<string>"
}{
"error": "<string>",
"code": "<string>",
"recovery": "<string>"
}{
"error": "<string>",
"limit": 2,
"remaining": 1,
"reset": 123
}Path Parameters
Your organization slug, as shown in your feedback URL on the Feedback page.
1 - 63^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i"acme"
Body
The feedback itself.
1 - 4000"The search tool times out when the query has quotes."
Short summary. When omitted, Notra writes one.
1 - 200"Search times out on quoted queries"
What kind of feedback this is. When omitted, Notra classifies it.
bug, feature, praise, question, other "bug"
Overall sentiment. When omitted, Notra classifies it from the message.
negative, neutral, positive "negative"
Channel the feedback arrived through.
mcp, api, sdk "mcp"
Project to file the feedback under.
1^[A-Za-z0-9_-]{1,100}$The agent or client that submitted the feedback.
1 - 200"claude-code"
1 - 200"claude-opus-5"
1 - 200"1.2.0"
1 - 2048Page or resource the feedback is about.
2048"https://docs.example.com/api/search"
Your own identifier for the user or session.
1 - 200Submitting the same key twice returns the original feedback instead of creating a duplicate.
1 - 200Arbitrary JSON attached to the feedback, up to 8 KB.
Show child attributes
Show child attributes
Was this page helpful?