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).

Table 1. Request Fields
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 AdultEntry server-side by validate_adults_array, which bounds the array length via MAX_ADULTS).

captcha_token

string (optional)

No

CAPTCHA token (required when CAPTCHA is enabled).

Cap permits Cloudflare Turnstile / reCAPTCHA v3 tokens which can run several KB — IDENTIFIER_LONG_MAX (1024) accommodates current providers without unbounded memory use.

children

object

No

Child subjects, as a JSON array (untyped here; deserialized into ChildEntry server-side by validate_children_array, which bounds the array length via MAX_CHILDREN).

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 ReportConfirmation.id used for status lookups.

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 raw_submission like the other Phase-2 reporter fields (#638).

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 ReporterType: anonymous, mandated, concerned_citizen (see craig-intake’s PUBLIC_REPORTER_TYPES).

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 ENUM_STRING_MAX so deserializing a malicious huge body can’t exhaust memory before the silent-drop check fires.

Responses
  • 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

Table 2. Parameters
Name In Required Description

id

path

Yes

Report ID

Responses
  • 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

Table 3. Parameters
Name In Required Description

id

path

Yes

Report ID returned by submit

Responses
  • 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

Table 4. Parameters
Name In Required Description

id

path

Yes

Report tracking reference

Responses
  • 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

Responses
  • 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

Table 5. Request Fields
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 AdultEntry server-side by validate_adults_array, which bounds the array length via MAX_ADULTS).

captcha_token

string (optional)

No

CAPTCHA token (required when CAPTCHA is enabled).

Cap permits Cloudflare Turnstile / reCAPTCHA v3 tokens which can run several KB — IDENTIFIER_LONG_MAX (1024) accommodates current providers without unbounded memory use.

children

object

No

Child subjects, as a JSON array (untyped here; deserialized into ChildEntry server-side by validate_children_array, which bounds the array length via MAX_CHILDREN).

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 ReportConfirmation.id used for status lookups.

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 raw_submission like the other Phase-2 reporter fields (#638).

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 ReporterType: anonymous, mandated, concerned_citizen (see craig-intake’s PUBLIC_REPORTER_TYPES).

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 ENUM_STRING_MAX so deserializing a malicious huge body can’t exhaust memory before the silent-drop check fires.

Responses
  • 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

Table 6. Parameters
Name In Required Description

id

path

Yes

Report ID returned by submit

Responses
  • 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

Table 7. Parameters
Name In Required Description

id

path

Yes

Tracking reference returned by submit

Responses
  • 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

Responses
  • 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}

Table 8. Parameters
Name In Required Description

kid

path

Yes

The signer-key id (JWS kid) to check

Responses
  • 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

Table 9. Request Fields
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

kid in the JWS header; globally unique.

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).

Responses
  • 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

Table 10. Request Fields
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 AdultEntry server-side by validate_adults_array, which bounds the array length via MAX_ADULTS).

captcha_token

string (optional)

No

CAPTCHA token (required when CAPTCHA is enabled).

Cap permits Cloudflare Turnstile / reCAPTCHA v3 tokens which can run several KB — IDENTIFIER_LONG_MAX (1024) accommodates current providers without unbounded memory use.

children

object

No

Child subjects, as a JSON array (untyped here; deserialized into ChildEntry server-side by validate_children_array, which bounds the array length via MAX_CHILDREN).

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 ReportConfirmation.id used for status lookups.

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 raw_submission like the other Phase-2 reporter fields (#638).

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 ReporterType: anonymous, mandated, concerned_citizen (see craig-intake’s PUBLIC_REPORTER_TYPES).

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 ENUM_STRING_MAX so deserializing a malicious huge body can’t exhaust memory before the silent-drop check fires.

Responses
  • 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.


Edit this page · latest