Public Intake API Reference
On this page
The stateless public edge: accepts child abuse and neglect reports from the public and from partner agencies, validates them, and forwards them to craig-cases. The edge holds no data of its own (ADR-017).
Endpoints
Partner
Submit a report via API key
POST /partner/v1/reports
In integrated mode, the X-JWS-Signature header is required and is
verified against craig-security’s signer-key registry. In standalone
mode, the JWS header is forwarded transparently to the upstream cases
service (which performs its own verification).
| Field | Type | Required | Description |
|---|---|---|---|
additional_info |
string (optional) |
No |
Any additional information the reporter wants to provide. |
admin_unit |
string |
Yes |
Administrative unit (county/region office) the report is routed to. |
adults |
object |
No |
Adult subjects, as a JSON array (untyped here; deserialized into
|
captcha_token |
string (optional) |
No |
CAPTCHA token (required when CAPTCHA is enabled). Cap permits Cloudflare Turnstile / reCAPTCHA v3 tokens which can run
several KB — |
children |
object |
No |
Child subjects, as a JSON array (untyped here; deserialized into
|
client_request_id |
UUID |
Yes |
ADR-062 §B (#1258): the client-minted, client-HELD submission id.
REQUIRED — the intake edge no longer mints one per inbound request
(the pre-#1258 double-create bug: an HTTP retry produced two cases
reports). Resubmitting the SAME id with the same substance replays
the original stored report; a divergent resubmit under the same id
is refused (409). A NEW id is a NEW submission. Distinct from the
server-assigned |
concern_description |
string |
Yes |
Free-text description of the concern. |
concern_type |
string |
Yes |
Concern category (e.g. neglect, physical_abuse). |
immediate_danger |
boolean |
No |
Whether the child is in immediate danger. |
incident_date |
date (optional) |
No |
Date the incident occurred (legacy date-only field). |
incident_datetime |
datetime (optional) |
No |
Date and time the incident occurred (RFC 3339). |
incident_location |
string (optional) |
No |
Where the incident occurred. |
indian_heritage |
string (optional) |
No |
Indian heritage indicator (ICWA screening). |
indian_heritage_details |
string (optional) |
No |
Free-text details about Indian heritage (ICWA screening). |
mandated_reporter_category |
string (optional) |
No |
Mandated-reporter profession category (e.g. physician, dentist) — set
when the reporter identifies as a mandated reporter. Captured in the
forwarded |
narrative |
object |
No |
Structured narrative payload (JSONB), stored as-is. |
reporter_city |
string (optional) |
No |
Reporter’s city. |
reporter_county |
string (optional) |
No |
Reporter’s county. |
reporter_email |
string (optional) |
No |
Reporter’s email address. |
reporter_first_name |
string (optional) |
No |
Reporter’s first name. |
reporter_is_household_member |
boolean (optional) |
No |
Whether the reporter is a member of the child’s household. |
reporter_is_primary_caregiver |
boolean (optional) |
No |
Whether the reporter is the child’s primary caregiver. |
reporter_is_self_reporting |
boolean (optional) |
No |
Whether the reporter is reporting about themselves. |
reporter_last_name |
string (optional) |
No |
Reporter’s last name. |
reporter_maltreater_relationship |
string (optional) |
No |
Reporter’s relationship to the alleged maltreater. |
reporter_phone |
string (optional) |
No |
Reporter’s phone number. |
reporter_relation |
string (optional) |
No |
Reporter’s relationship to the situation being reported. |
reporter_relationship_to_caregiver |
string (optional) |
No |
Reporter’s relationship to the caregiver. |
reporter_relationship_to_child |
string (optional) |
No |
Reporter’s relationship to the child. |
reporter_state |
string (optional) |
No |
Reporter’s state/territory code. |
reporter_street |
string (optional) |
No |
Reporter’s street address. |
reporter_type |
string |
Yes |
Reporter category. The public intake channel accepts a curated subset of
the canonical |
reporter_zip |
string (optional) |
No |
Reporter’s postal code. |
safety_concerns |
string (optional) |
No |
Any safety concerns relevant to a responding worker. |
source_system_id |
string (optional) |
No |
Source system tracking ID (for API submissions). |
website |
string |
No |
Honeypot field — if populated, the submission is silently dropped. Capped defensively at |
-
200: Report submitted
-
400: Validation error or missing JWS header
-
401: Invalid or missing API key, or JWS verification / partner-binding / replay failure
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
List attachments for a report (proxied to craig-cases)
GET /partner/v1/reports/{id}/attachments
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Report ID |
-
200: Attachment list
-
404: Report not found (or owned by a different partner)
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Upload an attachment to a report (proxied to craig-cases)
POST /partner/v1/reports/{id}/attachments
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Report ID returned by submit |
-
200: Attachment uploaded
-
400: Validation error
-
404: Report not found (or owned by a different partner)
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Check report status via API key
GET /partner/v1/reports/{id}/status
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Report tracking reference |
-
200: Report status
-
401: Invalid or missing API key
-
404: Report not found (or owned by a different partner)
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Public
Declared field-relevance rules (visibility + required-if)
GET /public/v1/intake-schema
-
200: Field-relevance schema
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Submit a public child abuse report
POST /public/v1/reports
| Field | Type | Required | Description |
|---|---|---|---|
additional_info |
string (optional) |
No |
Any additional information the reporter wants to provide. |
admin_unit |
string |
Yes |
Administrative unit (county/region office) the report is routed to. |
adults |
object |
No |
Adult subjects, as a JSON array (untyped here; deserialized into
|
captcha_token |
string (optional) |
No |
CAPTCHA token (required when CAPTCHA is enabled). Cap permits Cloudflare Turnstile / reCAPTCHA v3 tokens which can run
several KB — |
children |
object |
No |
Child subjects, as a JSON array (untyped here; deserialized into
|
client_request_id |
UUID |
Yes |
ADR-062 §B (#1258): the client-minted, client-HELD submission id.
REQUIRED — the intake edge no longer mints one per inbound request
(the pre-#1258 double-create bug: an HTTP retry produced two cases
reports). Resubmitting the SAME id with the same substance replays
the original stored report; a divergent resubmit under the same id
is refused (409). A NEW id is a NEW submission. Distinct from the
server-assigned |
concern_description |
string |
Yes |
Free-text description of the concern. |
concern_type |
string |
Yes |
Concern category (e.g. neglect, physical_abuse). |
immediate_danger |
boolean |
No |
Whether the child is in immediate danger. |
incident_date |
date (optional) |
No |
Date the incident occurred (legacy date-only field). |
incident_datetime |
datetime (optional) |
No |
Date and time the incident occurred (RFC 3339). |
incident_location |
string (optional) |
No |
Where the incident occurred. |
indian_heritage |
string (optional) |
No |
Indian heritage indicator (ICWA screening). |
indian_heritage_details |
string (optional) |
No |
Free-text details about Indian heritage (ICWA screening). |
mandated_reporter_category |
string (optional) |
No |
Mandated-reporter profession category (e.g. physician, dentist) — set
when the reporter identifies as a mandated reporter. Captured in the
forwarded |
narrative |
object |
No |
Structured narrative payload (JSONB), stored as-is. |
reporter_city |
string (optional) |
No |
Reporter’s city. |
reporter_county |
string (optional) |
No |
Reporter’s county. |
reporter_email |
string (optional) |
No |
Reporter’s email address. |
reporter_first_name |
string (optional) |
No |
Reporter’s first name. |
reporter_is_household_member |
boolean (optional) |
No |
Whether the reporter is a member of the child’s household. |
reporter_is_primary_caregiver |
boolean (optional) |
No |
Whether the reporter is the child’s primary caregiver. |
reporter_is_self_reporting |
boolean (optional) |
No |
Whether the reporter is reporting about themselves. |
reporter_last_name |
string (optional) |
No |
Reporter’s last name. |
reporter_maltreater_relationship |
string (optional) |
No |
Reporter’s relationship to the alleged maltreater. |
reporter_phone |
string (optional) |
No |
Reporter’s phone number. |
reporter_relation |
string (optional) |
No |
Reporter’s relationship to the situation being reported. |
reporter_relationship_to_caregiver |
string (optional) |
No |
Reporter’s relationship to the caregiver. |
reporter_relationship_to_child |
string (optional) |
No |
Reporter’s relationship to the child. |
reporter_state |
string (optional) |
No |
Reporter’s state/territory code. |
reporter_street |
string (optional) |
No |
Reporter’s street address. |
reporter_type |
string |
Yes |
Reporter category. The public intake channel accepts a curated subset of
the canonical |
reporter_zip |
string (optional) |
No |
Reporter’s postal code. |
safety_concerns |
string (optional) |
No |
Any safety concerns relevant to a responding worker. |
source_system_id |
string (optional) |
No |
Source system tracking ID (for API submissions). |
website |
string |
No |
Honeypot field — if populated, the submission is silently dropped. Capped defensively at |
-
200: Report submitted
-
400: Validation error
-
422: Mandated reporter must sign (SHINES) — use the signed channel
-
429: Rate limit exceeded
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Upload an attachment to a public report (proxied to craig-cases)
POST /public/v1/reports/{id}/attachments
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Report ID returned by submit |
-
200: Attachment uploaded
-
400: Validation error
-
404: Report not found
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Check report status by tracking reference
GET /public/v1/reports/{id}/status
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Tracking reference returned by submit |
-
200: Report status
-
404: Report not found
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Signed
List registered signer keys (metadata only, proxied to the keyring)
GET /signed/v1/keys
-
200: Registered-key metadata
-
404: View-keys list is not enabled
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Look up whether a signer key is active (proxied to the keyring)
GET /signed/v1/keys/by-kid/{kid}
| Name | In | Required | Description |
|---|---|---|---|
kid |
path |
Yes |
The signer-key id (JWS kid) to check |
-
200: The key is active (approved + unexpired)
-
404: The key is not active yet (pending / absent / revoked / expired)
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Register a browser-generated public signing key (proxied to the keyring)
POST /signed/v1/keys/register
| Field | Type | Required | Description |
|---|---|---|---|
algorithm |
string (optional) |
No |
Signing algorithm (defaults to ES256 if omitted). |
display_name |
string |
Yes |
Human-readable display name, e.g. "Dr. Jones". |
expires_at |
datetime (optional) |
No |
Optional key expiry. |
key_id |
string |
Yes |
|
public_key_jwk |
object |
Yes |
Public key as a JWK (RFC 7517). |
user_identifier |
string |
Yes |
Partner-scoped identifier for the signing person (email, employee id). |
-
200: Registered (pending admin approval)
-
400: Invalid registration
-
409: A key with that kid already exists
-
429: Signer-key registry at capacity
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Submit a report authenticated by a detached JWS (standalone SHINES)
POST /signed/v1/reports
| Field | Type | Required | Description |
|---|---|---|---|
additional_info |
string (optional) |
No |
Any additional information the reporter wants to provide. |
admin_unit |
string |
Yes |
Administrative unit (county/region office) the report is routed to. |
adults |
object |
No |
Adult subjects, as a JSON array (untyped here; deserialized into
|
captcha_token |
string (optional) |
No |
CAPTCHA token (required when CAPTCHA is enabled). Cap permits Cloudflare Turnstile / reCAPTCHA v3 tokens which can run
several KB — |
children |
object |
No |
Child subjects, as a JSON array (untyped here; deserialized into
|
client_request_id |
UUID |
Yes |
ADR-062 §B (#1258): the client-minted, client-HELD submission id.
REQUIRED — the intake edge no longer mints one per inbound request
(the pre-#1258 double-create bug: an HTTP retry produced two cases
reports). Resubmitting the SAME id with the same substance replays
the original stored report; a divergent resubmit under the same id
is refused (409). A NEW id is a NEW submission. Distinct from the
server-assigned |
concern_description |
string |
Yes |
Free-text description of the concern. |
concern_type |
string |
Yes |
Concern category (e.g. neglect, physical_abuse). |
immediate_danger |
boolean |
No |
Whether the child is in immediate danger. |
incident_date |
date (optional) |
No |
Date the incident occurred (legacy date-only field). |
incident_datetime |
datetime (optional) |
No |
Date and time the incident occurred (RFC 3339). |
incident_location |
string (optional) |
No |
Where the incident occurred. |
indian_heritage |
string (optional) |
No |
Indian heritage indicator (ICWA screening). |
indian_heritage_details |
string (optional) |
No |
Free-text details about Indian heritage (ICWA screening). |
mandated_reporter_category |
string (optional) |
No |
Mandated-reporter profession category (e.g. physician, dentist) — set
when the reporter identifies as a mandated reporter. Captured in the
forwarded |
narrative |
object |
No |
Structured narrative payload (JSONB), stored as-is. |
reporter_city |
string (optional) |
No |
Reporter’s city. |
reporter_county |
string (optional) |
No |
Reporter’s county. |
reporter_email |
string (optional) |
No |
Reporter’s email address. |
reporter_first_name |
string (optional) |
No |
Reporter’s first name. |
reporter_is_household_member |
boolean (optional) |
No |
Whether the reporter is a member of the child’s household. |
reporter_is_primary_caregiver |
boolean (optional) |
No |
Whether the reporter is the child’s primary caregiver. |
reporter_is_self_reporting |
boolean (optional) |
No |
Whether the reporter is reporting about themselves. |
reporter_last_name |
string (optional) |
No |
Reporter’s last name. |
reporter_maltreater_relationship |
string (optional) |
No |
Reporter’s relationship to the alleged maltreater. |
reporter_phone |
string (optional) |
No |
Reporter’s phone number. |
reporter_relation |
string (optional) |
No |
Reporter’s relationship to the situation being reported. |
reporter_relationship_to_caregiver |
string (optional) |
No |
Reporter’s relationship to the caregiver. |
reporter_relationship_to_child |
string (optional) |
No |
Reporter’s relationship to the child. |
reporter_state |
string (optional) |
No |
Reporter’s state/territory code. |
reporter_street |
string (optional) |
No |
Reporter’s street address. |
reporter_type |
string |
Yes |
Reporter category. The public intake channel accepts a curated subset of
the canonical |
reporter_zip |
string (optional) |
No |
Reporter’s postal code. |
safety_concerns |
string (optional) |
No |
Any safety concerns relevant to a responding worker. |
source_system_id |
string (optional) |
No |
Source system tracking ID (for API submissions). |
website |
string |
No |
Honeypot field — if populated, the submission is silently dropped. Capped defensively at |
-
200: Accepted + forwarded to SHINES
-
400: Malformed request body (post-auth)
-
401: Missing / invalid / replayed signature
-
429: Rate limit exceeded
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.