# Anonymous reporting

Reports use plain HTTP, outside JSON-RPC. Authentication and cookies are not required.
Do not send your name, email, phone number or other personal data. Read the
[reporting policy](/abuse-policy). There is no reply to anonymous reports and no
public reference status lookup.

1. Send `POST /api/v1/abuse/challenge` with exactly `{}` as JSON.
2. Solve the ALTCHA v1 SHA-256 challenge: find `number` in `0..maxNumber` so that
   SHA-256 of the UTF-8 bytes `salt + String(number)` equals `challenge`.
3. Base64-encode UTF-8 JSON containing `algorithm`, `challenge`, `number`, `salt`
   and `signature` and send it in `altcha` to `POST /api/v1/abuse/reports`.

```json
{
  "target": {"album": {"alias": "coast"}},
  "category": "privacy",
  "description": "This photo reveals a private location.",
  "good_faith": true,
  "altcha": "<base64 ALTCHA v1 payload>"
}
```

Use the album address you opened: exactly one of `alias`, `id`, `token` in
`target.album`. To report a photo, use `target: {"photo_id":"<uuid>"}` instead.
The server determines the photo's current album. Never send both targets.

Categories: `csam`, `ncii`, `privacy`, `illegal`, `violence`, `harassment`,
`copyright`, `spam`, `other`. Descriptions are normalized to NFC and limited to
2000 Unicode characters; `illegal`, `copyright` and `other` require a description.
`good_faith` must be `true`. Extra fields, including sender contact details, are refused.
The optional spam-trap `website` field must be omitted or empty.

Each proof expires after ten minutes and can be used once, even if its target is
unavailable. Changing its JSON field order or the optional `took` value does not
make it reusable. Both routes require `Content-Length` (at most 8192 bytes),
`Content-Type: application/json` (optional `charset=utf-8`) and same-origin browser
requests. No CORS headers are emitted.

Success is `202 {"reference":"R-7K4M-Q2WX"}`. The same reference shape is returned
for unavailable targets and silent duplicate reports. Sensitive reports concerning
previously published content remain possible after an album is hidden, a share link
is reset, or album publishing is disabled. Independently public photos are still
reportable with album publishing disabled.

| HTTP status | Meaning |
|---|---|
| 400 | `malformed`, `validation_failed` with `field`, or neutral `verification_failed` |
| 403 | Foreign Origin or Sec-Fetch-Site |
| 411 | Content-Length missing or chunked body |
| 413 | Declared body exceeds 8192 bytes |
| 415 | Unsupported Content-Type or charset |
| 429 | `rate_limited`, `retry_after_seconds` and `Retry-After` seconds |
| 503 | `reporting_disabled` or `temporarily_unavailable` |

Default hourly limits: 30 challenges and 5 submissions per IPv4 address or IPv6
/64 prefix, with an additional IPv6 /48 report limit. A report target is counted
once per day for the same source prefix, regardless of whether it was addressed
by UUID, alias or token. These source keys use daily salted HMACs in bounded
process memory; addresses are not stored with reports or written to request logs.
