curl --request GET \
--url https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback \
--header 'Authorization: Bearer <token>'import requests
url = "https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
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 => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback")
.header("Authorization", "Bearer <token>")
.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::Get.new(url)
request["Authorization"] = 'Bearer <token>'
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>"
}Get a project's pull-request feedback setting
Returns the pull-request controls in force for the project: when the Earnie summary comment appears, the inline review floor and cap, and the noise controls that decide which pull requests are scanned at all. A project that has never been configured reads the documented defaults — comment on success, medium floor, cap 10, scan drafts, scan bot authors, every base branch, every path — and the absence of a stored row IS that default rather than a missing value. locked and source say where the answer came from. When an organization has locked these controls, locked is true, source is organization, and the values returned are the organization’s.
curl --request GET \
--url https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback \
--header 'Authorization: Bearer <token>'import requests
url = "https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
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 => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://{tenant}.earnie.dev/v1/projects/{projectId}/pr-feedback")
.header("Authorization", "Bearer <token>")
.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::Get.new(url)
request["Authorization"] = 'Bearer <token>'
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>"
}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
Response
The project's 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