Public API
Target reader: SDK developers and backend developers verifying SDK config reads and feedback ingestion.
The public API uses contracts version 0.4.0-alpha.1 and is served locally at http://localhost:4000. It accepts SDK config reads, feedback report writes, and consent-gated attachment uploads. It is authenticated with X-Project-Key.
Routes
| Method | Path | Purpose |
|---|---|---|
GET |
/healthz |
Process liveness only. |
GET |
/readyz |
PostgreSQL and object-storage readiness. |
GET |
/v1/sdk/config?locale=zh-CN|en|ja |
Localized SDK config, privacy text, categories, attachment limits, and unchecked consent defaults. |
POST |
/v1/feedback/reports |
Create a player-initiated feedback report and consent snapshot. |
POST |
/v1/feedback/reports/{feedback_id}/attachments |
Upload a consent-gated attachment such as a screenshot or recent log. |
Liveness, readiness, and browser access
GET /healthz does not check dependencies. GET /readyz is unauthenticated and treats PostgreSQL and object storage as hard dependencies: it returns 200 ready only when both component statuses are ready; either dependency failure returns 503 unavailable. Responses use Cache-Control: no-store and omit raw dependency errors, endpoints, bucket names, and credentials.
The Public API intentionally has no browser CORS policy in Alpha. Its supported consumers are native Godot games and non-browser tooling; do not treat it as a browser-facing API or infer its state from the Admin API.
Minimal example
curl -X POST "http://localhost:4000/v1/feedback/reports" \
-H "Content-Type: application/json" \
-H "Accept-Language: en" \
-H "X-Project-Key: enb_pk_xxx" \
-H "Idempotency-Key: godot-demo-uuid-002" \
-d '{
"client_report_id": "godot-demo-uuid-002",
"trigger_source": "button",
"category": "suggestion",
"description": "The map marker would be easier to see with stronger contrast.",
"content_language": "en",
"player": {
"id_hash": "sha256:337180dda29405211bf7a37ea531367110370dc54db2298fcf4450f1749badb3"
},
"app": {
"environment": "test",
"release": "0.1.0",
"build_id": "dev-build-001",
"engine": "godot",
"engine_version": "4.x"
},
"game_context": {
"scene": "res://scenes/hub.tscn",
"level": "hub",
"extra": {}
},
"breadcrumbs": [],
"consents": {
"privacy_notice_version": "v1",
"locale": "en",
"player_confirmed_submit": true,
"screenshot_upload": false,
"recent_logs_upload": false,
"contact_upload": false,
"submitted_at": "2026-06-10T01:05:02Z"
},
"locale": "en",
"device": {
"platform": "macos",
"locale": "en"
}
}'
Expected success is 202 Accepted with a feedback_id and a multipart attachment endpoint.
Server defaults
client_report_id, trigger_source, category, description, and consents are the required report fields. Use app for environment/release/build/engine, device for platform and device facts, and player for optional identity/contact. Omitted runtime context stores unknown; engine defaults to godot. UI language resolves from locale, then Accept-Language, the project default and en; content_language and consent locale remain independent. Duplicate top-level runtime/contact fields and ui_locale are rejected. Use the current SDK package; old Alpha data and request formats are not migrated.
Common mistakes
- Do not omit
Idempotency-Keyon feedback creation. - Use a stable, per-attachment
Idempotency-Key(1–120 characters) for attachment retries. Reusing it with different attachment content returns409. - Avoid sending
recent_logswhenconsents.recent_logs_uploadisfalse; the server will drop inline logs and recordrecent_logs_dropped: trueif they are sent anyway. - Do not upload
screenshotattachments unless the saved report consent allows screenshots. - Do not reuse the example
player_id_hash; hash or pseudonymize your own player identifier before sending it. - Do not use the Project Key against
/admin/v1/*Admin API endpoints.
Next step
Use the Admin API to review accepted feedback.
Resource limits and startup configuration policy: Troubleshooting.