Public API resources
Contract updated October 12, 2026
SubraLabs publishes one small public API for anonymous Sense-Calibrator telemetry and for the diagnostic reports its users choose to send. Its complete, machine-readable contract is available as OpenAPI 3.1 JSON. No API key or user account is required.
When to use this API
The submission endpoint exists only for the Sense-Calibrator web tool. Call it only while the person using the tool has accepted the telemetry description currently shown by the tool. It is not a general contact API, analytics collector, model endpoint, or substitute for emailing SubraLabs. A rejected or unavailable telemetry request must never stop the calibration workflow.
The diagnostic report endpoint follows its own rule: call it only after the person using the tool has pressed Send to the developer and confirmed a dialog that shows the size and contents of the report. It does not depend on the telemetry consent, and a failed report must not stop the calibration workflow either; the tool keeps the report available for download.
The health endpoint may be used to determine whether the telemetry service is available. It does not promise that a later submission will be accepted and must not be polled aggressively.
Endpoints
GET /api/calib/health returns a minimal JSON health object. POST /api/calib/v1/sessions accepts the typed calibration record defined in the OpenAPI document and returns 204 No Content on success. Unknown fields and invalid values are rejected. The service stores no account, name, email address, request User-Agent, or IP address in the telemetry record.
POST /api/calib/v2/events accepts one CalibrationEventV2 per request: a Quick, guided or range calibration, a Write to memory attempt, how an unsaved calibration ended, a summary of resting stick noise, or a landing summary of where each stick stopped after being pushed at least 25% and released since the last calibration, or since the page opened if there was none (at most two per visit). Base fields are required; optional verification (Quick) and completion (Range) diagnostics and the rest timing fields sinceCalS, opsSince and landings keep older pages compatible. Quick reports the stability of existing verification attempts; Range reports reversal progress and missing completion checks. sinceCalS is the time since the last Quick or guided calibration of the page load, rounded to 10 seconds and capped at 3600; opsSince starts with that calibration's type and then lists the kinds of operation that followed it (Range, Write, reconnect, restart, confirmed power-off), each once and in order (all three fields are null if there was no such calibration or another controller was connected since); landings counts the releases since. All three are null when the visit had no such calibration. These are the only points in time in an event, always relative to that calibration; other times are durations. Unknown fields are rejected at every level, and every string is an enumerated value except a random per-page-load sid. Events carry no serial number, device identifier, free text or client timestamp; the service adds only the UTC day of receipt. The v1 endpoint remains available unchanged for earlier versions of the tool.
POST /api/calib/v2/diagnostics accepts one DiagnosticsReportV1 per request: a recording of up to 30 minutes with connections, operations and their results, where each stick stopped after every release, and the resting position once per second. Unknown fields are rejected at every level, and every embedded calibration event must also match CalibrationEventV2. All times are milliseconds from the start of the recording; there is no clock time, serial number, device identifier or raw input report. On success the service returns 201 Created with {"code": "SC-XXXXXXXX"}, a random code to quote in a GitHub issue. It stores the report unchanged plus the UTC day of receipt, sets the file's modification time to midnight UTC of that day, and deletes the report after 180 days. Reports share a global daily quota of 50 reports or 10 MB per UTC day and a total store cap; when either is reached the service answers 507.
Authentication and privacy
These endpoints do not use authentication. Browser submissions are limited to the documented Sense-Calibrator origins through CORS; CORS is not treated as authentication. The absence of credentials does not remove the need for explicit opt-in. The privacy policy describes the fields and the no-request-metadata boundary.
Rate limits
Calibration submissions are limited to 10 requests per IP address in a rolling 60-second window on /api/calib/v1/sessions, events to 30 per IP address in a separate 60-second window on /api/calib/v2/events, and diagnostic reports to 3 per IP address per hour and 6 per 24 hours on /api/calib/v2/diagnostics. Responses expose the current IETF draft conventions through RateLimit-Policy and RateLimit, plus compatibility fields RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A 429 response also includes Retry-After. Clients should use the headers they understand and never send more traffic because a displayed quota appears available.
Machine-readable errors
API errors use application/problem+json following RFC 9457. Every body contains type, title, status, detail, a stable code, and a resolution hint. The legacy error field mirrors detail so the existing calibrator remains compatible.
- invalid_request. Correct the JSON body against the OpenAPI schema before retrying.
- payload_too_large. Remove undocumented data and keep the body below 8 KB (v1), 4 KB (v2 events) or 512 KB (diagnostic reports).
- unsupported_media_type. Send uncompressed
application/jsonencoded as UTF-8. - rate_limit_exceeded. Wait for the number of seconds in
Retry-After. - storage_capacity_reached. Continue without telemetry and do not retry automatically. For a diagnostic report,
Retry-Afteris present when the daily quota is used up and gives the seconds until midnight UTC; without it, the store is full until old reports expire. - endpoint_not_found. Use a path and method listed in the OpenAPI document.
- internal_error. Continue without telemetry and do not retry immediately.
Agent and function-calling compatibility
Each operation in openapi.json has a unique operationId, a description, typed request and response schemas, and explicit failure responses. An agent may translate those operations into function tools, but it must preserve the usage and consent rules above. For a software project enquiry, use the human contact route instead.