Skip to content

Ingestion API

Header Hawk CSP Ingestion API v1.0.0

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

API for receiving CSP (Content Security Policy) violation reports from browsers. Supports both CSP Level 2 format (report-uri) and Reporting API format (report-to).

This API does not use traditional authentication. Instead, each site is assigned an 8-character ingestCode that is embedded in the URL path. This design is necessary because browsers cannot add custom headers to CSP report requests.

The ingestCode is:

  • Generated when a site is created
  • 8 characters, base62 (a-z, A-Z, 0-9)
  • Validated via edge cache for fast rejection of invalid codes
  • Can be regenerated if compromised

Example CSP header configuration:

Content-Security-Policy: default-src 'self'; report-uri https://ingest.headerhawk.com/csp/Xk9mP2nQ

Base URLs:

Web: Header Hawk

Ingestion

Code samples

const inputBody = '{
"csp-report": {
"document-uri": "http://example.com",
"referrer": "string",
"violated-directive": "string",
"effective-directive": "string",
"original-policy": "string",
"disposition": "enforce",
"blocked-uri": "string",
"status-code": 0,
"source-file": "string",
"line-number": 0,
"column-number": 0,
"script-sample": "string"
}
}';
const headers = {
'Content-Type':'application/csp-report',
'Accept':'application/json'
};
fetch('https://ingest.headerhawk.com/csp/{ingestCode}',
{
method: 'POST',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
import requests
headers = {
'Content-Type': 'application/csp-report',
'Accept': 'application/json'
}
r = requests.post('https://ingest.headerhawk.com/csp/{ingestCode}', headers = headers)
print(r.json())
Terminal window
# You can also use wget
curl -X POST https://ingest.headerhawk.com/csp/{ingestCode} \
-H 'Content-Type: application/csp-report' \
-H 'Accept: application/json'

POST /csp/{ingestCode}

Submit CSP violation report

Receives CSP violation reports from browsers. This endpoint URL is configured in the customer’s CSP header via report-uri or report-to directives.

The endpoint accepts both:

  • CSP Level 2 format (Content-Type: application/csp-report)
  • Reporting API format (Content-Type: application/reports+json)

Site identification is via the ingestCode path parameter. Invalid codes are rejected at the edge without database lookup.

Body parameter

{
"csp-report": {
"document-uri": "http://example.com",
"referrer": "string",
"violated-directive": "string",
"effective-directive": "string",
"original-policy": "string",
"disposition": "enforce",
"blocked-uri": "string",
"status-code": 0,
"source-file": "string",
"line-number": 0,
"column-number": 0,
"script-sample": "string"
}
}

Parameters

NameInTypeRequiredDescription
ingestCodepathstringtrue8-character site identifier. This code is provided when creating a site
bodybodyCspReportPayloadtruenone

ingestCode: 8-character site identifier. This code is provided when creating a site and should be kept confidential to prevent unauthorized report submission.

Example responses

202 Response

{
"status": "accepted",
"reportId": "string"
}

400 Response

{
"error": "invalid_format",
"message": "Unable to parse CSP report"
}

404 Response

{
"error": "not_found",
"message": "Site not found"
}

410 Response

{
"error": "gone",
"message": "Site is no longer active"
}

429 Response

{
"error": "rate_limited",
"message": "Too many requests"
}

Responses

StatusMeaningDescriptionSchema
202AcceptedReport accepted for processingInline
400Bad RequestInvalid report formatError
404Not FoundInvalid ingestCode or site not foundError
410GoneSite is deactivatedError
429Too Many RequestsRate limit exceededError

Response Schema

Status Code 202

NameTypeRequiredRestrictionsDescription
» statusstringfalsenonenone
» reportIdstringfalsenoneUnique ID assigned to this report (or batch)
PropertyValue
statusaccepted
StatusHeaderTypeFormatDescription
429Retry-AfterintegerSeconds until rate limit resets

Operations

Code samples

const headers = {
'Accept':'application/json'
};
fetch('https://ingest.headerhawk.com/health',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
import requests
headers = {
'Accept': 'application/json'
}
r = requests.get('https://ingest.headerhawk.com/health', headers = headers)
print(r.json())
Terminal window
# You can also use wget
curl -X GET https://ingest.headerhawk.com/health \
-H 'Accept: application/json'

GET /health

Health check endpoint

Example responses

200 Response

{
"status": "healthy",
"timestamp": "2019-08-24T14:15:22Z"
}

Responses

StatusMeaningDescriptionSchema
200OKService is healthyInline

Response Schema

Status Code 200

NameTypeRequiredRestrictionsDescription
» statusstringfalsenonenone
» timestampstring(date-time)falsenonenone
PropertyValue
statushealthy

CspReportPayload

{
"csp-report": {
"document-uri": "http://example.com",
"referrer": "string",
"violated-directive": "string",
"effective-directive": "string",
"original-policy": "string",
"disposition": "enforce",
"blocked-uri": "string",
"status-code": 0,
"source-file": "string",
"line-number": 0,
"column-number": 0,
"script-sample": "string"
}
}

CSP Level 2 report format (sent with report-uri directive)

NameTypeRequiredRestrictionsDescription
csp-reportobjectfalsenonenone
» document-uristring(uri)truenonenone
» referrerstringfalsenonenone
» violated-directivestringtruenonenone
» effective-directivestringfalsenonenone
» original-policystringtruenonenone
» dispositionstringfalsenonenone
» blocked-uristringfalsenonenone
» status-codeintegerfalsenonenone
» source-filestringfalsenonenone
» line-numberintegerfalsenonenone
» column-numberintegerfalsenonenone
» script-samplestringfalsenonenone
PropertyValue
dispositionenforce
dispositionreport

ReportingApiPayload

{
"age": 0,
"body": {
"blockedURL": "string",
"disposition": "enforce",
"documentURL": "http://example.com",
"effectiveDirective": "string",
"lineNumber": 0,
"columnNumber": 0,
"originalPolicy": "string",
"referrer": "string",
"sample": "string",
"sourceFile": "string",
"statusCode": 0
},
"type": "csp-violation",
"url": "http://example.com",
"user_agent": "string"
}

Reporting API format (sent with report-to directive)

NameTypeRequiredRestrictionsDescription
ageintegerfalsenoneMilliseconds between violation and report
bodyobjecttruenonenone
» blockedURLstringfalsenonenone
» dispositionstringfalsenonenone
» documentURLstring(uri)truenonenone
» effectiveDirectivestringtruenonenone
» lineNumberintegerfalsenonenone
» columnNumberintegerfalsenonenone
» originalPolicystringtruenonenone
» referrerstringfalsenonenone
» samplestringfalsenonenone
» sourceFilestringfalsenonenone
» statusCodeintegerfalsenonenone
typestringtruenonenone
urlstring(uri)falsenonenone
user_agentstringfalsenonenone
PropertyValue
dispositionenforce
dispositionreport
typecsp-violation

Error

{
"error": "string",
"message": "string",
"details": {}
}
NameTypeRequiredRestrictionsDescription
errorstringtruenoneError code
messagestringtruenoneHuman-readable error message
detailsobjectfalsenoneAdditional error context