Start vulnerability triage
curl --request POST \
--url https://neo.api.projectdiscovery.io/api/v1/triage \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"items": [
{
"external_id": "<string>",
"context": "<string>"
}
],
"model": "<string>"
}
'import requests
url = "https://neo.api.projectdiscovery.io/api/v1/triage"
payload = {
"items": [
{
"external_id": "<string>",
"context": "<string>"
}
],
"model": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({items: [{external_id: '<string>', context: '<string>'}], model: '<string>'})
};
fetch('https://neo.api.projectdiscovery.io/api/v1/triage', 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://neo.api.projectdiscovery.io/api/v1/triage",
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([
'items' => [
[
'external_id' => '<string>',
'context' => '<string>'
]
],
'model' => '<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://neo.api.projectdiscovery.io/api/v1/triage"
payload := strings.NewReader("{\n \"items\": [\n {\n \"external_id\": \"<string>\",\n \"context\": \"<string>\"\n }\n ],\n \"model\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://neo.api.projectdiscovery.io/api/v1/triage")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"items\": [\n {\n \"external_id\": \"<string>\",\n \"context\": \"<string>\"\n }\n ],\n \"model\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://neo.api.projectdiscovery.io/api/v1/triage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"items\": [\n {\n \"external_id\": \"<string>\",\n \"context\": \"<string>\"\n }\n ],\n \"model\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"external_id": "<string>",
"error": {
"code": "<string>",
"message": "<string>"
},
"task_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
],
"summary": {
"accepted": 123,
"rejected": 123,
"skipped": 123
}
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}Triage
Start vulnerability triage
Start one or more Neo triage runs for reports from HackerOne, GitHub Security Advisories, or Security Inbox (Gmail). Neo builds the triage prompt and queues each run on the same durable task-start path as normal tasks — custom free-form task text is not accepted. Up to 20 items per request. Items already being triaged are skipped. Requires Neo AI access and available credits.
POST
/
api
/
v1
/
triage
Start vulnerability triage
curl --request POST \
--url https://neo.api.projectdiscovery.io/api/v1/triage \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"items": [
{
"external_id": "<string>",
"context": "<string>"
}
],
"model": "<string>"
}
'import requests
url = "https://neo.api.projectdiscovery.io/api/v1/triage"
payload = {
"items": [
{
"external_id": "<string>",
"context": "<string>"
}
],
"model": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({items: [{external_id: '<string>', context: '<string>'}], model: '<string>'})
};
fetch('https://neo.api.projectdiscovery.io/api/v1/triage', 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://neo.api.projectdiscovery.io/api/v1/triage",
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([
'items' => [
[
'external_id' => '<string>',
'context' => '<string>'
]
],
'model' => '<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://neo.api.projectdiscovery.io/api/v1/triage"
payload := strings.NewReader("{\n \"items\": [\n {\n \"external_id\": \"<string>\",\n \"context\": \"<string>\"\n }\n ],\n \"model\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://neo.api.projectdiscovery.io/api/v1/triage")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"items\": [\n {\n \"external_id\": \"<string>\",\n \"context\": \"<string>\"\n }\n ],\n \"model\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://neo.api.projectdiscovery.io/api/v1/triage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"items\": [\n {\n \"external_id\": \"<string>\",\n \"context\": \"<string>\"\n }\n ],\n \"model\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"external_id": "<string>",
"error": {
"code": "<string>",
"message": "<string>"
},
"task_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
],
"summary": {
"accepted": 123,
"rejected": 123,
"skipped": 123
}
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}{
"error": "Bad request",
"code": "user_spending_cap_reached",
"error_id": "<string>",
"kind": "forbidden request",
"message": "<string>"
}Authorizations
BearerAuthApiKeyAuth
JWT authentication token
Body
application/json
Required array length:
1 - 20 elementsShow child attributes
Show child attributes
Source for every item in this request.
Available options:
hackerone, github, gmail Optional model to use for triage. An invalid value rejects the entire request before any items are started.
⌘I

