Documentation contents
Modules
Modules outside the health score (rankings, Search Console, backlinks, security, logs). They carry trends, never a score.
Read rank tracking
GET
/v1/projects/{project}/positions
Tracked keywords and their latest position for the project domain, with the
period summary. A keyword with measured: false was never checked; a
keyword with measured: true and position: null was checked and is out of
the top 100. Requires a plan that includes the module.
- Required scopes
- positions:read
- Rate-limit cost
- 5 unit(s)
Parameters
-
projectpath · string (uuid) · required -
periodquery · string · optional
Responses
-
200OK. -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/positions" \
-H "Authorization: Bearer $NESSFLOW_TOKEN"
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('GET', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/positions', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/positions', {
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/positions",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"status": "unconfigured",
"tracker": {
"location": "string",
"country": "string",
"language": "string",
"device": "string",
"active": true,
"last_tracked_on": "2026-10-01"
},
"period": {
"preset": "string",
"from": "2026-10-01",
"to": "2026-10-01"
},
"summary": {
"average_position": 0.5,
"ranking_keywords": 42,
"measured_keywords": 42,
"tracked_keywords": 42,
"top3": 42,
"top10": 42,
"visibility_percent": 0.5,
"improved": 42,
"declined": 42,
"entered": 42,
"exited": 42
},
"keywords": [
{
"keyword": "string",
"active": true,
"measured": true,
"position": 42,
"url": "https://exemple.fr/",
"delta_1d": 42,
"delta_7d": 42,
"delta_30d": 42,
"search_volume": 42,
"keyword_difficulty": 42,
"search_intent": "string",
"serp_features": [
"string"
]
}
],
"quota": {
"used": 42,
"limit": 100,
"remaining": 100
}
}
}
Track keywords
POST
/v1/projects/{project}/tracked-keywords
Puts keywords under daily rank tracking (at most 100 per request). A keyword is
identified by its canonical form (lowercase, single spaces), which the response
returns. A keyword already known to the project as a candidate is adopted. This
opens a recurring daily spend: it counts against the plan pool
positions.tracked_keywords (plan_limit.positions.tracked_keywords) and the
per-project ceiling (keywords.project_limit), so an Idempotency-Key is
required.
- Required scopes
- positions:write
- Rate-limit cost
- 1 unit(s)
- Idempotency-Key
- Idempotency-Key required
- Rate-limit cost
- Consumes a plan quota
Parameters
-
projectpath · string (uuid) · required
Request body
-
keywordsstring[] · required
Responses
-
200OK. -
400Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`). -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
409The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready). -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords" \
-H "Authorization: Bearer $NESSFLOW_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"keywords":["string"]}'
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('POST', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
'json' => [
'keywords' => [
'string',
],
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"keywords": [
"string"
]
}),
});
const data = await response.json();
Python
import os
import uuid
import requests
response = requests.post(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"keywords": [
"string",
],
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"tracked": [
"string"
],
"already_tracked": [
"string"
]
}
}
Stop tracking keywords
POST
/v1/projects/{project}/tracked-keywords/untrack
Removes keywords from tracking without deleting them: their paid history stays,
and their slots are freed. Never refused by billing. Unknown or untracked keywords
are ignored; untracked lists those that changed.
- Required scopes
- positions:write
- Rate-limit cost
- 1 unit(s)
- Idempotency-Key
- Idempotency-Key accepted
Parameters
-
projectpath · string (uuid) · required
Request body
-
keywordsstring[] · required
Responses
-
200OK. -
400Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`). -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
409The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready). -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/untrack" \
-H "Authorization: Bearer $NESSFLOW_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"keywords":["string"]}'
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('POST', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/untrack', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
'json' => [
'keywords' => [
'string',
],
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/untrack', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"keywords": [
"string"
]
}),
});
const data = await response.json();
Python
import os
import uuid
import requests
response = requests.post(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/untrack",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"keywords": [
"string",
],
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"untracked": [
"string"
]
}
}
Pause tracked keywords
POST
/v1/projects/{project}/tracked-keywords/pause
Suspends the daily check of tracked keywords, which frees their slots in the
plan pool. keywords.not_tracked if one of them is not tracked.
- Required scopes
- positions:write
- Rate-limit cost
- 1 unit(s)
- Idempotency-Key
- Idempotency-Key accepted
Parameters
-
projectpath · string (uuid) · required
Request body
-
keywordsstring[] · required
Responses
-
200OK. -
400Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`). -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
409The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready). -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/pause" \
-H "Authorization: Bearer $NESSFLOW_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"keywords":["string"]}'
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('POST', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/pause', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
'json' => [
'keywords' => [
'string',
],
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/pause', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"keywords": [
"string"
]
}),
});
const data = await response.json();
Python
import os
import uuid
import requests
response = requests.post(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/pause",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"keywords": [
"string",
],
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"active": true,
"changed": [
"string"
]
}
}
Resume tracked keywords
POST
/v1/projects/{project}/tracked-keywords/resume
Resumes the daily check of paused keywords. Resuming takes a slot back in the
plan pool (plan_limit.positions.tracked_keywords), so an Idempotency-Key is
required.
- Required scopes
- positions:write
- Rate-limit cost
- 1 unit(s)
- Idempotency-Key
- Idempotency-Key required
- Rate-limit cost
- Consumes a plan quota
Parameters
-
projectpath · string (uuid) · required
Request body
-
keywordsstring[] · required
Responses
-
200OK. -
400Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`). -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
409The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready). -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/resume" \
-H "Authorization: Bearer $NESSFLOW_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"keywords":["string"]}'
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('POST', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/resume', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
'json' => [
'keywords' => [
'string',
],
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/resume', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"keywords": [
"string"
]
}),
});
const data = await response.json();
Python
import os
import uuid
import requests
response = requests.post(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/resume",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"keywords": [
"string",
],
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"active": true,
"changed": [
"string"
]
}
}
Check a keyword now
POST
/v1/projects/{project}/tracked-keywords/check
Queues an immediate live check of one tracked keyword (202); the position
appears in the rank tracking read once measured. One immediate check per keyword
per day (keywords.already_checked_today), within the plan daily quota
(plan_limit.positions.live_checks_per_day) and monthly spend cap.
- Required scopes
- positions:write
- Rate-limit cost
- 1 unit(s)
- Idempotency-Key
- Idempotency-Key required
- Rate-limit cost
- Consumes a plan quota
Parameters
-
projectpath · string (uuid) · required
Request body
-
keywordstring · required
Responses
-
202OK. -
400Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`). -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
409The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready). -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/check" \
-H "Authorization: Bearer $NESSFLOW_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"keyword":"string"}'
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('POST', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/check', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
'json' => [
'keyword' => 'string',
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/check', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"keyword": "string"
}),
});
const data = await response.json();
Python
import os
import uuid
import requests
response = requests.post(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/check",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"keyword": "string",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"keyword": "string",
"status": "queued",
"date": "2026-10-01"
}
}
Read Search Console data
GET
/v1/projects/{project}/search-console
Performance totals and daily series (from the linked property), and the
indexation inspection totals. unconfigured means no property is linked,
pending that it is linked but not synced yet.
- Required scopes
- search_console:read
- Rate-limit cost
- 5 unit(s)
Parameters
-
projectpath · string (uuid) · required -
periodquery · string · optional
Responses
-
200OK. -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/search-console" \
-H "Authorization: Bearer $NESSFLOW_TOKEN"
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('GET', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/search-console', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/search-console', {
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/search-console",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"status": "unconfigured",
"property": "string",
"performance": {
"period": {
"preset": "string",
"from": "2026-10-01",
"to": "2026-10-01"
},
"totals": {
"clicks": 42,
"impressions": 42,
"ctr_percent": 0.5,
"average_position": 0.5
},
"daily": [
{
"date": "2026-10-01",
"clicks": 42,
"impressions": 42,
"average_position": 0.5
}
]
},
"indexation": {
"inspected": 42,
"indexed": 42,
"excluded": 42,
"canonical_conflicts": 42,
"last_inspected_at": "2026-10-01T09:30:00Z"
}
}
}
Read the backlink profile summary
GET
/v1/projects/{project}/backlinks
Latest daily measurement of the current target. Daily new and lost counters overlap and must not be summed.
- Required scopes
- backlinks:read
- Rate-limit cost
- 1 unit(s)
Parameters
-
projectpath · string (uuid) · required
Responses
-
200OK. -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/backlinks" \
-H "Authorization: Bearer $NESSFLOW_TOKEN"
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('GET', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/backlinks', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/backlinks', {
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/backlinks",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"status": "unconfigured",
"target": "string",
"latest": {
"date": "2026-10-01",
"rank": 42,
"backlinks": 42,
"referring_domains": 42,
"referring_main_domains": 42,
"referring_pages": 42,
"broken_backlinks": 42,
"broken_pages": 42,
"spam_score": 42,
"new_backlinks": 42,
"lost_backlinks": 42,
"new_referring_domains": 42,
"lost_referring_domains": 42
}
}
}
Read security signals
GET
/v1/projects/{project}/security
Passive security signals of the project site, with their status. An
incomplete scan (scan.complete: false) does not mean nothing was found;
score: null means unknown, never zero. Texts follow Accept-Language.
- Required scopes
- security:read
- Rate-limit cost
- 5 unit(s)
Parameters
-
projectpath · string (uuid) · required
Responses
-
200OK. -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/security" \
-H "Authorization: Bearer $NESSFLOW_TOKEN"
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('GET', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/security', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/security', {
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/security",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"status": "string",
"target": "string",
"scan": {
"status": "string",
"running": true,
"complete": true,
"results_truncated": true,
"started_at": "2026-10-01T09:30:00Z",
"finished_at": "2026-10-01T09:30:00Z"
},
"score": 42,
"counts": {
"problems": 42,
"informational": 42,
"fixed": 42,
"masked": 42,
"ignored": 42,
"falsePositive": 42
},
"findings": [
{
"key": "string",
"severity": "critical",
"status": "string",
"location": "string",
"title": "string",
"explanation": "string",
"action": "string",
"first_seen_at": "2026-10-01T09:30:00Z",
"last_seen_at": "2026-10-01T09:30:00Z",
"fixed_at": "2026-10-01T09:30:00Z"
}
]
}
}
Read server log analysis
GET
/v1/projects/{project}/logs
Hits by audience (humans, search bots, AI bots, others) over the period, with the days actually covered by logs.
- Required scopes
- logs:read
- Rate-limit cost
- 5 unit(s)
Parameters
-
projectpath · string (uuid) · required -
periodquery · string · optional
Responses
-
200OK. -
401Missing, invalid or expired token, or a member who left the team. -
403The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`). -
404No such resource for the token's team. Resources of another team answer 404 as well, never 403. -
422Invalid query or body values (`validation_failed`), with `errors` by field. -
429The plan rate limit is exhausted for one window.
cURL
curl "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/logs" \
-H "Authorization: Bearer $NESSFLOW_TOKEN"
PHP
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
$response = $client->request('GET', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/logs', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
],
]);
$data = json_decode((string) $response->getBody(), true);
JavaScript
const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/logs', {
headers: {
Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/logs",
headers={
"Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
},
timeout=30,
)
response.raise_for_status()
data = response.json()
Response example
{
"data": {
"project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
"status": "pending",
"period": {
"preset": "string",
"from": "2026-10-01",
"to": "2026-10-01",
"days": 42,
"days_with_logs": 42
},
"totals": {
"hits": 42,
"bot_hits": 42,
"human_hits": 42,
"bytes": 42
},
"daily": [
{
"date": "2026-10-01",
"humans": 42,
"search": 42,
"ai": 42,
"others": 42
}
],
"gaps": [
{
"from": "2026-10-01",
"to": "2026-10-01",
"days": 42
}
]
}
}