Skip to documentation content
Docs

Evidence

Create metadata, upload bytes, and confirm evidence.

Metadata and limits #

Allowed MIME types: image/png, image/jpeg, application/pdf. Filenames use at most 120 safe characters with a terminal extension matching the MIME: .png, .jpg, .jpeg, or .pdf. File size is 1 byte through 10 MiB. A report supports at most 9 evidence intents. File bytes do not belong inside the report JSON.

Create additional evidence #

POST/api/v1/reports/{report_id}/evidence
Scope
reports:write
Environment
Customer Sandbox and Production
Required headers
Authorization, Content-Type, Idempotency-Key

POST /api/v1/reports/{report_id}/evidence requires reports:write and Idempotency-Key.

Request body
{
  "filename": "evidence.png",
  "content_type": "image/png",
  "declared_size": 12345
}
Successful 201 response
{
  "request_id": "req_123e4567-e89b-42d3-a456-426614174000",
  "report_id": "rpt_123e4567-e89b-42d3-a456-426614174000",
  "evidence_id": "evd_123e4567-e89b-42d3-a456-426614174000",
  "upload_url": "https://uploads.example.invalid/signed-object",
  "expires_at": "2026-10-15T13:00:00.000Z",
  "required_headers": {
    "content-type": "image/png"
  },
  "confirm_url": "/api/v1/reports/rpt_123e4567-e89b-42d3-a456-426614174000/evidence/evd_123e4567-e89b-42d3-a456-426614174000/confirm",
  "confirmed": false
}
Create evidence intent — cURL
# Run in your server environment. Requires reports:write.
curl --request POST "$GOWALY_BASE_URL/api/v1/reports/$REPORT_ID/evidence" \
  --header "Authorization: Bearer $GOWALY_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data '{
  "filename": "evidence.png",
  "content_type": "image/png",
  "declared_size": 12345
}'

Response keys: request_id, report_id, evidence_id, upload_url, expires_at, required_headers, confirm_url, confirmed.

Upload bytes #

PUT file bytes to the returned upload_url. Set Content-Type to the exact lower-case required_headers["content-type"] value returned by the API. The authorization is private, covers one object, and expires after 7200 seconds (2 hours). Do not persist or log the upload URL.

Set UPLOAD_URL and REQUIRED_CONTENT_TYPE from the returned upload_url and required_headers. Send every returned required header exactly. Do not attach the GoWaly Bearer key to this signed storage upload.

Upload evidence bytes — cURL
# Use the upload_url and required_headers returned by the API.
curl --request PUT "$UPLOAD_URL" \
  --header "Content-Type: $REQUIRED_CONTENT_TYPE" \
  --data-binary "@evidence.png"

Confirm evidence #

POST/api/v1/reports/{report_id}/evidence/{evidence_id}/confirm
Scope
reports:write
Environment
Customer Sandbox and Production
Required headers
Authorization

POST /api/v1/reports/{report_id}/evidence/{evidence_id}/confirm requires reports:write and has no request body. Response keys: request_id, report_id, evidence_id, confirmed, already_confirmed. confirmed is true; reconfirmation is idempotent.

Request body
(no request body)
Successful 200 response
{
  "request_id": "req_123e4567-e89b-42d3-a456-426614174000",
  "report_id": "rpt_123e4567-e89b-42d3-a456-426614174000",
  "evidence_id": "evd_123e4567-e89b-42d3-a456-426614174000",
  "confirmed": true,
  "already_confirmed": false
}
Confirm evidence — cURL
# Run in your server environment. Requires reports:write.
curl --request POST "$GOWALY_BASE_URL/api/v1/reports/$REPORT_ID/evidence/$EVIDENCE_ID/confirm" \
  --header "Authorization: Bearer $GOWALY_API_KEY"

Missing or cross-client resources return generic 404 REPORT_NOT_FOUND or EVIDENCE_NOT_FOUND without revealing ownership.

Common errors #

HTTPMeaning
400Invalid metadata, file type, size, or confirmation
403Wrong environment or missing reports:write
404Generic report or evidence not found
409Idempotency conflict or evidence limit reached
429Burst rate or monthly quota exceeded