Skip to main content

Report apparent CSAM to the NCMEC CyberTipline

When your platform encounters apparent child sexual abuse material (CSAM) in media, detection alone does not close the legal loop. US providers must report it to the National Center for Missing & Exploited Children (NCMEC) CyberTipline and preserve the report contents for 90 days. This runbook walks the full loop on Orbit: where the detection signal comes from, how to read the reporting obligation, how to assemble and preserve a filing-ready report with the two /api/v1/messages/media/csam-report endpoints, and which half of the work belongs to you.
This page is operator guidance, not legal advice. Whether and how 18 U.S.C. §2258A applies to your organization is a question for your counsel.

When the obligation applies to you

18 U.S.C. §2258A applies to providers of an electronic communication service or remote computing service to the public in the United States. If your organization uses Orbit to send or receive SMS, MMS, WhatsApp, RCS, or email media for US users, you are in that position, and the duty fires when your service encounters apparent CSAM. “Apparent” is the statutory standard: a credible automated or human detection signal triggers the reporting duty; you do not need certainty, and you do not investigate or adjudicate the material yourself. Orbit already produces the detection signals you need:
  • The vision-agent image pre-screen classifies uploaded and attached imagery and withholds anything it flags as unsafe, including the csam category.
  • The inbound media threat scan quarantines dangerous inbound MMS and attachment bytes before they reach an inbox or the message store (see Inbound media threat scan and quarantine model).
Neither surface reports on its own. The endpoints in this runbook take their signal and close the loop: detect, preserve, report.

Where the detection signal comes from

The reporting endpoint recognizes four detection sources. Read them from the requirements endpoint (detection_sources) rather than hard-coding them. Automated signals (image_moderation_shield, media_threat_scan, external_classifier) file only at or above the minimum confidence gate, min_confidence (0.5 by default, returned by the requirements endpoint). A signal below the gate is refused with a 422 so a borderline classifier verdict is never filed as a statutory report on its own. If a human reviewer confirms the material, resubmit with source: "analyst_review" and it files at any confidence. Media ingested before these scanning surfaces were live carries no automated signal. For that older media, run your normal human review and file with source: "analyst_review".

Read the reporting requirement

GET /api/v1/messages/media/csam-report/requirements returns the obligation exactly as the platform models it: the statute, the preservation window, the incident types, the report lifecycle states, the detection sources, the required report elements, and the confidence gate. Read it at integration time and when your compliance program is audited; it is the contract your reporting pipeline codes against.
The data object of the response:
The required_elements list is what §2258A(b) contemplates in operator language: who was involved and how they connected, when the material was observed, where the sender appeared to be, the material itself identified by hash, and the surrounding communication. The sections below show where each element lands in the request.

Assemble and file a report

POST /api/v1/messages/media/csam-report assembles the filing-ready report and preserves its summary for the statutory window in one call. The body has three parts:
  • incident (required): the channel, direction, the message or conversation the material arrived on, when it was detected, and the detection block: source, apparent_csam, confidence in [0, 1], and the detector that produced the verdict.
  • media (required, 1 to 50 items): each item carries at least one hash (md5, sha1, sha256, or photodna), plus filename, content type, size, a storage_ref pointing at the preserved bytes (never the bytes themselves), and when it was observed.
  • subscriber (optional): the involved party’s contact reference, handle (MSISDN, email, or social handle), IP address, coarse location, and the timestamps the material was observed. Include what you lawfully hold; these are the §2258A(b)(1),(3) elements.
  • reporter (optional): your ESP name, NCMEC-assigned ESP id, and contact details. Omitted fields fall back to your organization reference until you set your NCMEC-registered identity.
This worked example files a report from a vision-agent pre-screen verdict at 0.91 confidence. The hashes below are the MD5/SHA-1/SHA-256 of the string The quick brown fox jumps over the lazy dog; substitute the hashes of the actual preserved file.
On success the endpoint returns 201 with the assembled report in data. The report starts life assembled: built, preserved, and awaiting transmission. preservation.preserve_until is the §2258A(h) deadline, 90 days after assembly. The data object:
When the signal does not warrant a statutory report, the endpoint returns 422 and preserves nothing:
A 422 is the conservative path doing its job: an over-report has its own legal cost. It is not an error in your integration.

What Orbit does and what you do

The split is sharp, and it is the part of this runbook to get right before an audit. Orbit assembles the filing-ready artifact: it validates the detection signal against the confidence gate, normalizes the report to the CyberTipline shape, computes the 90-day preservation deadline, and preserves a PII-safe summary of the report (references and media hashes, not the subscriber’s handle, IP, or location) in your tamper-evident audit ledger. Orbit does not transmit anything to NCMEC on your behalf. You are the reporting ESP. Registration with NCMEC, the CyberTipline credentials, and the transmission step that moves a report from assembled through queued, submitted, and acknowledged are tenant-owned controls.
Tenant-owned: register your organization with NCMEC as a reporting ESP and provision the transmission adapter that submits your assembled reports (NCMEC CyberTipline, missingkids.org/cybertipline). Until those credentials exist, reports are assembled and preserved for you, but nothing leaves the platform. Your counsel and your NCMEC onboarding define the transmission cadence; Orbit holds the artifact and the preservation record.

Evidence preservation and the 90-day window

§2258A(h) requires you to preserve the report contents and the involved material for 90 days. Every filed report writes a tamper-evident audit entry (action messages.csam_report.filed, resource csam_cybertip_report, keyed by the ctr_… report id) carrying the incident classification, the detection source and confidence, the media hashes, and preserve_until. Read it where you read the rest of the ledger: Settings → Audit log in the dashboard, or the async export covered in Audit Log Export; the live filters are in Audit Log. Two operational consequences:
  • The preserved entry and the media it references outrank routine retention purges for the statutory window. If your retention schedule or an erasure request would delete the quarantined bytes or the audit entry before preserve_until, the statutory preservation obligation wins for that window; coordinate erasure work with your pending reports.
  • The audit summary deliberately holds references, not the subscriber PII the filing carries. The full report is reconstructable from the referenced message at filing time, so keep the underlying message and media readable until preserve_until as well.

Troubleshooting

422 CSAM_REPORT_NOT_WARRANTED. Either apparent_csam was false or the automated signal’s confidence was below min_confidence (0.5 by default; read the live value from the requirements endpoint). If a human reviewer confirms the material, resubmit the same body with detection.source: "analyst_review"; human confirmations file at any confidence. 400 on the media hashes. Every media item needs at least one of md5, sha1, sha256, or photodna, and the hex hashes must be their full length (32, 40, and 64 hex characters respectively). Hash the preserved bytes, not a thumbnail or a transcode. 401 or 403. The GET requires your read scope and the POST your write scope on Messages. Check the API key used by your reporting pipeline, not the key your dashboard session uses. No detection signal on older media. Media ingested before the scanning surfaces were live has no automated verdict. File those after human review with source: "analyst_review", and see Tenant migration operations if your organization still has a platform migration pending.

See also