curl --request PUT \
--url https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"inline_comment_cap": 5,
"base_branch_filter": [
"<string>"
],
"path_filters": [
"<string>"
]
}
'import requests
url = "https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
payload = {
"inline_comment_cap": 5,
"base_branch_filter": ["<string>"],
"path_filters": ["<string>"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
inline_comment_cap: 5,
base_branch_filter: ['<string>'],
path_filters: ['<string>']
})
};
fetch('https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback', 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://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'inline_comment_cap' => 5,
'base_branch_filter' => [
'<string>'
],
'path_filters' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
payload := strings.NewReader("{\n \"inline_comment_cap\": 5,\n \"base_branch_filter\": [\n \"<string>\"\n ],\n \"path_filters\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.put("https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"inline_comment_cap\": 5,\n \"base_branch_filter\": [\n \"<string>\"\n ],\n \"path_filters\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"inline_comment_cap\": 5,\n \"base_branch_filter\": [\n \"<string>\"\n ],\n \"path_filters\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"summary_comment": "always",
"inline_severity_floor": "critical",
"inline_comment_cap": 5,
"draft_pull_requests": "scan",
"bot_authors": "scan",
"base_branch_filter": [
"<string>"
],
"path_filters": [
"<string>"
],
"locked": true,
"source": "default"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}Set a project's pull-request controls
Replaces the project’s pull-request controls. Every control is required: this is a complete snapshot, not a patch, so a client sends back what it read. summary_comment decides when the Earnie summary comment appears; inline_severity_floor and inline_comment_cap shape the inline review. The four noise controls decide which pull requests are scanned at all — drafts, bot authors, base branches and changed paths. None of them changes a verdict. Policy evaluation, the gate and the Earnie check run are unaffected, and nothing here retroactively adds or removes anything on pull requests already scanned. Refused with 409 settings_locked when the organization has locked these controls; change them at /v1/organization/pr-feedback instead. locked and source in the body are read-only and ignored.
curl --request PUT \
--url https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"inline_comment_cap": 5,
"base_branch_filter": [
"<string>"
],
"path_filters": [
"<string>"
]
}
'import requests
url = "https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
payload = {
"inline_comment_cap": 5,
"base_branch_filter": ["<string>"],
"path_filters": ["<string>"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
inline_comment_cap: 5,
base_branch_filter: ['<string>'],
path_filters: ['<string>']
})
};
fetch('https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback', 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://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'inline_comment_cap' => 5,
'base_branch_filter' => [
'<string>'
],
'path_filters' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
payload := strings.NewReader("{\n \"inline_comment_cap\": 5,\n \"base_branch_filter\": [\n \"<string>\"\n ],\n \"path_filters\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.put("https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"inline_comment_cap\": 5,\n \"base_branch_filter\": [\n \"<string>\"\n ],\n \"path_filters\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"inline_comment_cap\": 5,\n \"base_branch_filter\": [\n \"<string>\"\n ],\n \"path_filters\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"summary_comment": "always",
"inline_severity_floor": "critical",
"inline_comment_cap": 5,
"draft_pull_requests": "scan",
"bot_authors": "scan",
"base_branch_filter": [
"<string>"
],
"path_filters": [
"<string>"
],
"locked": true,
"source": "default"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}{
"code": "<string>",
"message": "<string>"
}Authorizations
An Earnie API key, sent as Authorization: Bearer sk_earnie_.... Create one under Settings > API keys. The key's scopes decide which operations it may call.
Path Parameters
Body
Per-project pull-request controls. Presentation controls govern how much Earnie says about a pull request it scanned; noise controls govern which pull requests are worth scanning at all. Neither governs what a scan concludes: no control here reaches policy evaluation, the gate, a finding state or a verdict, so no setting on this object can turn a block into a pass.
always posts the summary on every terminal verdict, success included — the default, and what a project with no stored setting reads. on_failure_only refreshes an existing summary comment but never creates one on a passing gate: a pull request that has never failed gets no comment, while one that did stops showing a stale red verdict.
always, on_failure_only Lowest finding severity eligible for an inline review comment. Defaults to medium; lower-severity findings remain visible in Earnie and in the pull-request summary.
critical, high, medium, low, info Maximum inline comments in one COMMENT review. Defaults to 10; overflow remains in the pull-request summary. Zero disables inline placement without changing policy evaluation or the check.
0 <= x <= 10What to do with a draft pull request. scan — the default, and what Earnie did before this control existed — scans it like any other. skip leaves it unscanned until it is marked ready for review, at which point the provider's ready_for_review event scans it.
scan, skip What to do with a pull request opened by a provider bot account — a dependency updater, release automation, a code generator. scan is the default. skip leaves them unscanned, which on repositories where bots open most pull requests is the largest single source of check noise.
scan, skip Allow-list of base-branch patterns. A pull request targeting a branch none of them matches is not scanned. EMPTY MEANS EVERY BASE BRANCH, not none. Patterns support exact names, *, ?, [], and prefix/** for a whole namespace.
50Allow-list of changed-file patterns. A pull request is scanned only when it touches at least one matching file. EMPTY MEANS EVERY PATH. Earnie scans when it cannot be sure the filter excludes the change: if the provider will not say which files changed, or answers a truncated list with no match, the pull request is scanned anyway — a filter may only suppress a scan on evidence.
50Response
The updated pull-request feedback setting.
Per-project pull-request controls. Presentation controls govern how much Earnie says about a pull request it scanned; noise controls govern which pull requests are worth scanning at all. Neither governs what a scan concludes: no control here reaches policy evaluation, the gate, a finding state or a verdict, so no setting on this object can turn a block into a pass.
always posts the summary on every terminal verdict, success included — the default, and what a project with no stored setting reads. on_failure_only refreshes an existing summary comment but never creates one on a passing gate: a pull request that has never failed gets no comment, while one that did stops showing a stale red verdict.
always, on_failure_only Lowest finding severity eligible for an inline review comment. Defaults to medium; lower-severity findings remain visible in Earnie and in the pull-request summary.
critical, high, medium, low, info Maximum inline comments in one COMMENT review. Defaults to 10; overflow remains in the pull-request summary. Zero disables inline placement without changing policy evaluation or the check.
0 <= x <= 10What to do with a draft pull request. scan — the default, and what Earnie did before this control existed — scans it like any other. skip leaves it unscanned until it is marked ready for review, at which point the provider's ready_for_review event scans it.
scan, skip What to do with a pull request opened by a provider bot account — a dependency updater, release automation, a code generator. scan is the default. skip leaves them unscanned, which on repositories where bots open most pull requests is the largest single source of check noise.
scan, skip Allow-list of base-branch patterns. A pull request targeting a branch none of them matches is not scanned. EMPTY MEANS EVERY BASE BRANCH, not none. Patterns support exact names, *, ?, [], and prefix/** for a whole namespace.
50Allow-list of changed-file patterns. A pull request is scanned only when it touches at least one matching file. EMPTY MEANS EVERY PATH. Earnie scans when it cannot be sure the filter excludes the change: if the provider will not say which files changed, or answers a truncated list with no match, the pull request is scanned anyway — a filter may only suppress a scan on evidence.
50Whether these values come from an organization lock rather than from the project. When true, PUT on this resource is refused with 409 settings_locked and the values are changed at /v1/organization/pr-feedback. Ignored in a request body.
Where the effective answer came from: organization for a locked organization layer, project for the project's own stored settings, default when neither exists. Ignored in a request body.
default, project, organization