> For the complete documentation index, see [llms.txt](https://docs.mymedtrics.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mymedtrics.com/api-reference/connect-api/scores.md).

# Scores

Gradebook scores (PHI/FERPA). Legacy analog is /api/gradebook/scores/.

## List scores.

> Returns cursor-paged gradebook scores scoped to the authenticated API app tenant (program→institution). Requires scores:read scope. PHI/FERPA.

```json
{"openapi":"3.1.0","info":{"title":"Medtrics Connect API","version":"2026-10-27"},"tags":[{"name":"Scores","description":"Gradebook scores (PHI/FERPA). Legacy analog is /api/gradebook/scores/."}],"servers":[{"url":"https://sandbox.mymedtrics.com","description":"Client sandbox — shared demo tenant, X-Medtrics-Sandbox-Key or a sandbox API app"},{"url":"https://{client}.mymedtrics.com","description":"Your Medtrics instance","variables":{"client":{"default":"<client-name>","description":"The tenant subdomain Medtrics assigns to your institution"}}}],"security":[{"BearerToken":[]},{"SandboxApiKey":[]}],"components":{"securitySchemes":{"BearerToken":{"type":"http","scheme":"bearer"},"SandboxApiKey":{"type":"apiKey","in":"header","name":"X-Medtrics-Sandbox-Key"}},"parameters":{"ApiDateHeader":{"name":"Medtrics-API-Date","in":"header","required":true,"description":"API contract date. Use 2026-10-27 for this version. Contract dates select request behavior: rotation creates require explicit placement references from 2026-10-27; earlier accepted dates retain compatibility handling. Unknown dates return HTTP 400 with error.code unsupported_api_date.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"Limit":{"name":"limit","in":"query","required":false,"description":"Maximum number of records to return per page. The server may return fewer rows than requested. Values above the maximum (100) are silently clamped to 100. Values below the minimum (1) are silently clamped to 1. The effective value after clamping is always returned in pagination.limit so callers can detect that they hit the gateway ceiling. Per-client max_page_size overrides are documented as a tenant-configurable lower cap that never raises the public ceiling.\n","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"Cursor":{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},"ProgramIdQuery":{"name":"program_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by program public ID (prog_ prefix). Returns only records belonging to this program."},"LearnerIdQuery":{"name":"learner_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by learner public ID (learner_ prefix). Returns only records belonging to this learner."},"LegacyIdQuery":{"name":"legacy_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by legacy source ID from etl_id_registry. Useful for bridge lookups."}},"responses":{"ScoreListResponse":{"description":"Cursor-paged score records (PHI/FERPA).","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Score"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"BadRequest":{"description":"Invalid request parameters.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"Missing or invalid credentials.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Credential lacks tenant visibility or required scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimited":{"description":"Request or API app rate limit exceeded.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InternalError":{"description":"Unexpected server error.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"headers":{"MedtricsRequestId":{"description":"Correlates all gateway logs for the request.","schema":{"type":"string"}},"MedtricsApiDate":{"description":"API contract date applied to the request.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Request limit for the current window.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Remaining requests in the current window.","schema":{"type":"string"}},"RateLimitReset":{"description":"Unix seconds when the current rate-limit window resets.","schema":{"type":"string"}}},"schemas":{"Score":{"type":"object","description":"A gradebook score scoped to the authenticated API app tenant (program→institution). Legacy analog is /api/gradebook/scores/ (Score). PHI/FERPA.","required":["id","legacy_id","learner_id","program_id","score_type_id","score_date","is_final","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ID of the score (score_ prefix). Backed by scores.id."},"legacy_id":{"type":["string","null"],"description":"Legacy SIS integer ID (as string) from etl_id_registry (source_entity_type='score'), minted on create."},"learner_id":{"type":"string","description":"Public ID of the learner (learner_ prefix). Backed by scores.learner_id."},"learner_legacy_id":{"type":["string","null"]},"program_id":{"type":"string","description":"Public ID of the program (prog_ prefix). Backed by scores.program_id."},"program_legacy_id":{"type":["string","null"]},"score_type_id":{"type":"string","description":"Public ID of the score type (stype_ prefix). Backed by scores.score_type_id."},"score_type_legacy_id":{"type":["string","null"]},"status_id":{"type":["string","null"],"description":"Public ID of the score status (sstat_ prefix). Backed by scores.status_id."},"block_schedule_id":{"type":["string","null"],"description":"Public ID of the clinical placement (rotsched_ prefix). Backed by scores.block_schedule_id (classic user_schedule)."},"block_schedule_legacy_id":{"type":["string","null"]},"score_date":{"type":"string","format":"date"},"numeric_score":{"type":["number","null"]},"letter_grade":{"type":["string","null"]},"percentile":{"type":["number","null"]},"is_final":{"type":"boolean"},"notes":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Pagination":{"type":"object","description":"Cursor pagination envelope. Exposes only limit and next_cursor. Count fields (approximate_total, total_count_exact, or any equivalent) are intentionally absent and reserved for future Medtrics-API-Date additions once a concrete partner use case justifies a count strategy per route. pagination.limit is the effective page size after server-side clamp, not the value the client requested.","required":["limit","next_cursor"],"properties":{"limit":{"type":"integer","description":"Effective page size after server-side clamping. Compare to your requested limit to detect ceiling enforcement."},"next_cursor":{"type":["string","null"],"description":"Opaque keyset cursor. Pass as the cursor query parameter on the next request. null when no more pages exist."}}},"ErrorEnvelope":{"type":"object","required":["error"],"description":"Structured error envelope. error.code is the machine-readable discriminant. Typed detail schemas are provided for codes where structured data aids client remediation. Use the discriminator.mapping to select the correct variant schema; for all other codes see GenericApiError.\n","properties":{"error":{"anyOf":[{"$ref":"#/components/schemas/InvalidStatusError"},{"$ref":"#/components/schemas/InvalidWebhookEventsError"},{"$ref":"#/components/schemas/RateLimitedError"},{"$ref":"#/components/schemas/CursorResourceMismatchError"},{"$ref":"#/components/schemas/InvalidIdError"},{"$ref":"#/components/schemas/UnsupportedApiDateError"},{"$ref":"#/components/schemas/InactiveClientError"},{"$ref":"#/components/schemas/InvalidWebhookUrlError"},{"$ref":"#/components/schemas/GenericApiError"}],"discriminator":{"propertyName":"code","mapping":{"invalid_status":"#/components/schemas/InvalidStatusError","invalid_webhook_events":"#/components/schemas/InvalidWebhookEventsError","rate_limited":"#/components/schemas/RateLimitedError","cursor_resource_mismatch":"#/components/schemas/CursorResourceMismatchError","invalid_id":"#/components/schemas/InvalidIdError","unsupported_api_date":"#/components/schemas/UnsupportedApiDateError","inactive_client":"#/components/schemas/InactiveClientError","invalid_webhook_url":"#/components/schemas/InvalidWebhookUrlError"}}}}},"InvalidStatusError":{"description":"Returned when a status query parameter value is outside the allowed enum. HTTP 400. details.field identifies the parameter; details.allowed lists every accepted value.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_status"},"details":{"type":"object","required":["field","allowed"],"additionalProperties":false,"description":"Structured remediation data for invalid_status.","properties":{"field":{"type":"string","description":"Query parameter name that received the invalid value (e.g. enrollment_status, status).\n"},"allowed":{"type":"array","items":{"type":"string"},"description":"Full list of accepted values for the parameter."}}}}}]},"ApiErrorBase":{"type":"object","required":["code","message","request_id"],"description":"Common fields shared by every Connect API error response.","properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable error description."},"request_id":{"type":"string","description":"Request correlation ID. Include this value when reporting issues to support alongside the Medtrics-Request-ID response header.\n"}}},"InvalidWebhookEventsError":{"description":"Returned when event_types contains values not in the approved Connect API event list, or when event_types is empty. HTTP 400. details.unsupported_events lists the rejected entries (empty array when event_types was missing or entirely empty).\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_webhook_events"},"details":{"type":"object","required":["unsupported_events"],"additionalProperties":false,"description":"Structured remediation data for invalid_webhook_events.","properties":{"unsupported_events":{"type":"array","items":{"type":"string"},"description":"Event type strings that are not approved Connect API event names. Empty array indicates event_types was missing or contained only invalid entries.\n"}}}}}]},"RateLimitedError":{"description":"Returned when the request or API app rate limit is exceeded. HTTP 429. details.retry_after_seconds indicates the wait duration before retrying.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"rate_limited"},"details":{"type":"object","required":["retry_after_seconds"],"additionalProperties":false,"description":"Structured remediation data for rate_limited.","properties":{"retry_after_seconds":{"type":"integer","description":"Seconds to wait before retrying. Mirrors the Retry-After response header value.\n"}}}}}]},"CursorResourceMismatchError":{"description":"Returned when the cursor was issued for a different resource type than the endpoint being called. HTTP 400. details.expected_resource is the resource this endpoint serves; details.cursor_resource is what the cursor encodes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"cursor_resource_mismatch"},"details":{"type":"object","required":["expected_resource","cursor_resource"],"additionalProperties":false,"description":"Structured remediation data for cursor_resource_mismatch.","properties":{"expected_resource":{"type":"string","description":"Resource type this endpoint serves (e.g. programs, learners)."},"cursor_resource":{"type":"string","description":"Resource type encoded in the submitted cursor."}}}}}]},"InvalidIdError":{"description":"Returned when a path parameter public ID does not match the expected prefix for the resource. HTTP 400. details.field is the parameter name; details.expected_prefix is the required ID prefix.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_id"},"details":{"type":"object","required":["field","expected_prefix"],"additionalProperties":false,"description":"Structured remediation data for invalid_id.","properties":{"field":{"type":"string","description":"Path or query parameter name that received the invalid ID."},"expected_prefix":{"type":"string","description":"Required ID prefix for this parameter."}}}}}]},"UnsupportedApiDateError":{"description":"Returned when the Medtrics-API-Date header is missing, malformed (not YYYY-MM-DD), or not a supported contract date. HTTP 400. details.supported_dates lists all accepted values. details.reason is one of \"missing\", \"malformed\", or \"not_supported\".\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"unsupported_api_date"},"details":{"type":"object","required":["reason","supported_dates"],"additionalProperties":false,"description":"Structured remediation data for unsupported_api_date.","properties":{"reason":{"type":"string","enum":["missing","malformed","not_supported"],"description":"Specific cause: \"missing\" when the header is absent, \"malformed\" when the value is not YYYY-MM-DD format, \"not_supported\" when the format is valid but the date is not a known contract date.\n"},"supported_dates":{"type":"array","items":{"type":"string"},"description":"All accepted Medtrics-API-Date values."}}}}}]},"InactiveClientError":{"description":"Returned when the authenticated API client is revoked, expired, deleted, or in a non-active status. HTTP 403. No structured details beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"inactive_client"}}}]},"InvalidWebhookUrlError":{"description":"Returned when target_url fails HTTPS validation or is otherwise rejected. HTTP 422. No structured details field beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"invalid_webhook_url"}}}]},"GenericApiError":{"description":"Catch-all error variant for codes that carry no structured remediation data (invalid_cursor, not_found, invalid_credentials, scope_not_allowed, invalid_webhook_tolerance, internal_error, and any future codes not covered by a typed variant in the discriminator.mapping). details is absent or empty for these codes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"details":{"type":"object","additionalProperties":true,"description":"Absent or empty for most generic error codes."}}}]}}},"paths":{"/connect/scores":{"get":{"operationId":"listScores","tags":["Scores"],"summary":"List scores.","description":"Returns cursor-paged gradebook scores scoped to the authenticated API app tenant (program→institution). Requires scores:read scope. PHI/FERPA.","parameters":[{"$ref":"#/components/parameters/ApiDateHeader"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/ProgramIdQuery"},{"$ref":"#/components/parameters/LearnerIdQuery"},{"$ref":"#/components/parameters/LegacyIdQuery"}],"responses":{"200":{"$ref":"#/components/responses/ScoreListResponse"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Create a score.

> Creates a gradebook score. Requires scores:write scope. learner/program/score\_type FKs are scope-checked; score\_type is validated (leaf, program-usable, value\_mode); grader\_id is null on the API path. PHI/FERPA.

```json
{"openapi":"3.1.0","info":{"title":"Medtrics Connect API","version":"2026-10-27"},"tags":[{"name":"Scores","description":"Gradebook scores (PHI/FERPA). Legacy analog is /api/gradebook/scores/."}],"servers":[{"url":"https://sandbox.mymedtrics.com","description":"Client sandbox — shared demo tenant, X-Medtrics-Sandbox-Key or a sandbox API app"},{"url":"https://{client}.mymedtrics.com","description":"Your Medtrics instance","variables":{"client":{"default":"<client-name>","description":"The tenant subdomain Medtrics assigns to your institution"}}}],"security":[{"BearerToken":[]},{"SandboxApiKey":[]}],"components":{"securitySchemes":{"BearerToken":{"type":"http","scheme":"bearer"},"SandboxApiKey":{"type":"apiKey","in":"header","name":"X-Medtrics-Sandbox-Key"}},"parameters":{"ApiDateHeader":{"name":"Medtrics-API-Date","in":"header","required":true,"description":"API contract date. Use 2026-10-27 for this version. Contract dates select request behavior: rotation creates require explicit placement references from 2026-10-27; earlier accepted dates retain compatibility handling. Unknown dates return HTTP 400 with error.code unsupported_api_date.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}},"responses":{"ScoreItemResponse":{"description":"Single score record (PHI/FERPA).","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Score"}}}}}},"BadRequest":{"description":"Invalid request parameters.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"Missing or invalid credentials.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Credential lacks tenant visibility or required scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"NotFound":{"description":"Resource not found or outside tenant scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"UnprocessableEntity":{"description":"Request payload is syntactically valid but fails HTTPS validation. Used for createWebhookSubscription when target_url is not a valid HTTPS URL. invalid_webhook_events (HTTP 400) and invalid_webhook_tolerance (HTTP 400) are returned via the BadRequest response, not here.\n","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimited":{"description":"Request or API app rate limit exceeded.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InternalError":{"description":"Unexpected server error.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"headers":{"MedtricsRequestId":{"description":"Correlates all gateway logs for the request.","schema":{"type":"string"}},"MedtricsApiDate":{"description":"API contract date applied to the request.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Request limit for the current window.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Remaining requests in the current window.","schema":{"type":"string"}},"RateLimitReset":{"description":"Unix seconds when the current rate-limit window resets.","schema":{"type":"string"}}},"schemas":{"Score":{"type":"object","description":"A gradebook score scoped to the authenticated API app tenant (program→institution). Legacy analog is /api/gradebook/scores/ (Score). PHI/FERPA.","required":["id","legacy_id","learner_id","program_id","score_type_id","score_date","is_final","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ID of the score (score_ prefix). Backed by scores.id."},"legacy_id":{"type":["string","null"],"description":"Legacy SIS integer ID (as string) from etl_id_registry (source_entity_type='score'), minted on create."},"learner_id":{"type":"string","description":"Public ID of the learner (learner_ prefix). Backed by scores.learner_id."},"learner_legacy_id":{"type":["string","null"]},"program_id":{"type":"string","description":"Public ID of the program (prog_ prefix). Backed by scores.program_id."},"program_legacy_id":{"type":["string","null"]},"score_type_id":{"type":"string","description":"Public ID of the score type (stype_ prefix). Backed by scores.score_type_id."},"score_type_legacy_id":{"type":["string","null"]},"status_id":{"type":["string","null"],"description":"Public ID of the score status (sstat_ prefix). Backed by scores.status_id."},"block_schedule_id":{"type":["string","null"],"description":"Public ID of the clinical placement (rotsched_ prefix). Backed by scores.block_schedule_id (classic user_schedule)."},"block_schedule_legacy_id":{"type":["string","null"]},"score_date":{"type":"string","format":"date"},"numeric_score":{"type":["number","null"]},"letter_grade":{"type":["string","null"]},"percentile":{"type":["number","null"]},"is_final":{"type":"boolean"},"notes":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ErrorEnvelope":{"type":"object","required":["error"],"description":"Structured error envelope. error.code is the machine-readable discriminant. Typed detail schemas are provided for codes where structured data aids client remediation. Use the discriminator.mapping to select the correct variant schema; for all other codes see GenericApiError.\n","properties":{"error":{"anyOf":[{"$ref":"#/components/schemas/InvalidStatusError"},{"$ref":"#/components/schemas/InvalidWebhookEventsError"},{"$ref":"#/components/schemas/RateLimitedError"},{"$ref":"#/components/schemas/CursorResourceMismatchError"},{"$ref":"#/components/schemas/InvalidIdError"},{"$ref":"#/components/schemas/UnsupportedApiDateError"},{"$ref":"#/components/schemas/InactiveClientError"},{"$ref":"#/components/schemas/InvalidWebhookUrlError"},{"$ref":"#/components/schemas/GenericApiError"}],"discriminator":{"propertyName":"code","mapping":{"invalid_status":"#/components/schemas/InvalidStatusError","invalid_webhook_events":"#/components/schemas/InvalidWebhookEventsError","rate_limited":"#/components/schemas/RateLimitedError","cursor_resource_mismatch":"#/components/schemas/CursorResourceMismatchError","invalid_id":"#/components/schemas/InvalidIdError","unsupported_api_date":"#/components/schemas/UnsupportedApiDateError","inactive_client":"#/components/schemas/InactiveClientError","invalid_webhook_url":"#/components/schemas/InvalidWebhookUrlError"}}}}},"InvalidStatusError":{"description":"Returned when a status query parameter value is outside the allowed enum. HTTP 400. details.field identifies the parameter; details.allowed lists every accepted value.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_status"},"details":{"type":"object","required":["field","allowed"],"additionalProperties":false,"description":"Structured remediation data for invalid_status.","properties":{"field":{"type":"string","description":"Query parameter name that received the invalid value (e.g. enrollment_status, status).\n"},"allowed":{"type":"array","items":{"type":"string"},"description":"Full list of accepted values for the parameter."}}}}}]},"ApiErrorBase":{"type":"object","required":["code","message","request_id"],"description":"Common fields shared by every Connect API error response.","properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable error description."},"request_id":{"type":"string","description":"Request correlation ID. Include this value when reporting issues to support alongside the Medtrics-Request-ID response header.\n"}}},"InvalidWebhookEventsError":{"description":"Returned when event_types contains values not in the approved Connect API event list, or when event_types is empty. HTTP 400. details.unsupported_events lists the rejected entries (empty array when event_types was missing or entirely empty).\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_webhook_events"},"details":{"type":"object","required":["unsupported_events"],"additionalProperties":false,"description":"Structured remediation data for invalid_webhook_events.","properties":{"unsupported_events":{"type":"array","items":{"type":"string"},"description":"Event type strings that are not approved Connect API event names. Empty array indicates event_types was missing or contained only invalid entries.\n"}}}}}]},"RateLimitedError":{"description":"Returned when the request or API app rate limit is exceeded. HTTP 429. details.retry_after_seconds indicates the wait duration before retrying.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"rate_limited"},"details":{"type":"object","required":["retry_after_seconds"],"additionalProperties":false,"description":"Structured remediation data for rate_limited.","properties":{"retry_after_seconds":{"type":"integer","description":"Seconds to wait before retrying. Mirrors the Retry-After response header value.\n"}}}}}]},"CursorResourceMismatchError":{"description":"Returned when the cursor was issued for a different resource type than the endpoint being called. HTTP 400. details.expected_resource is the resource this endpoint serves; details.cursor_resource is what the cursor encodes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"cursor_resource_mismatch"},"details":{"type":"object","required":["expected_resource","cursor_resource"],"additionalProperties":false,"description":"Structured remediation data for cursor_resource_mismatch.","properties":{"expected_resource":{"type":"string","description":"Resource type this endpoint serves (e.g. programs, learners)."},"cursor_resource":{"type":"string","description":"Resource type encoded in the submitted cursor."}}}}}]},"InvalidIdError":{"description":"Returned when a path parameter public ID does not match the expected prefix for the resource. HTTP 400. details.field is the parameter name; details.expected_prefix is the required ID prefix.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_id"},"details":{"type":"object","required":["field","expected_prefix"],"additionalProperties":false,"description":"Structured remediation data for invalid_id.","properties":{"field":{"type":"string","description":"Path or query parameter name that received the invalid ID."},"expected_prefix":{"type":"string","description":"Required ID prefix for this parameter."}}}}}]},"UnsupportedApiDateError":{"description":"Returned when the Medtrics-API-Date header is missing, malformed (not YYYY-MM-DD), or not a supported contract date. HTTP 400. details.supported_dates lists all accepted values. details.reason is one of \"missing\", \"malformed\", or \"not_supported\".\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"unsupported_api_date"},"details":{"type":"object","required":["reason","supported_dates"],"additionalProperties":false,"description":"Structured remediation data for unsupported_api_date.","properties":{"reason":{"type":"string","enum":["missing","malformed","not_supported"],"description":"Specific cause: \"missing\" when the header is absent, \"malformed\" when the value is not YYYY-MM-DD format, \"not_supported\" when the format is valid but the date is not a known contract date.\n"},"supported_dates":{"type":"array","items":{"type":"string"},"description":"All accepted Medtrics-API-Date values."}}}}}]},"InactiveClientError":{"description":"Returned when the authenticated API client is revoked, expired, deleted, or in a non-active status. HTTP 403. No structured details beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"inactive_client"}}}]},"InvalidWebhookUrlError":{"description":"Returned when target_url fails HTTPS validation or is otherwise rejected. HTTP 422. No structured details field beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"invalid_webhook_url"}}}]},"GenericApiError":{"description":"Catch-all error variant for codes that carry no structured remediation data (invalid_cursor, not_found, invalid_credentials, scope_not_allowed, invalid_webhook_tolerance, internal_error, and any future codes not covered by a typed variant in the discriminator.mapping). details is absent or empty for these codes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"details":{"type":"object","additionalProperties":true,"description":"Absent or empty for most generic error codes."}}}]}}},"paths":{"/connect/scores":{"post":{"operationId":"createScore","tags":["Scores"],"summary":"Create a score.","description":"Creates a gradebook score. Requires scores:write scope. learner/program/score_type FKs are scope-checked; score_type is validated (leaf, program-usable, value_mode); grader_id is null on the API path. PHI/FERPA.","parameters":[{"$ref":"#/components/parameters/ApiDateHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["learner_id","program_id","score_type_id","score_date"],"properties":{"learner_id":{"type":"string","description":"Public ID (learner_ prefix)."},"program_id":{"type":"string","description":"Public ID (prog_ prefix)."},"score_type_id":{"type":"string","description":"Public ID (stype_ prefix)."},"score_date":{"type":"string","format":"date"},"numeric_score":{"type":"number","nullable":true},"status_id":{"type":"string","nullable":true,"description":"Public ID (sstat_ prefix); required for status_only score types."},"letter_grade":{"type":"string","nullable":true},"percentile":{"type":"number","nullable":true},"block_schedule_id":{"type":"string","nullable":true,"description":"Public ID (rotsched_ prefix) of the clinical placement."},"graded_course_rotation_id":{"type":"string","nullable":true,"description":"Public ID (gcr_ prefix). Its default rubric derives status_id + letter_grade on insert."},"notes":{"type":"string","nullable":true}}}}}},"responses":{"201":{"$ref":"#/components/responses/ScoreItemResponse"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Get a score.

> Returns one score when it belongs to the authenticated API app tenant. Requires scores:read scope. PHI/FERPA.

```json
{"openapi":"3.1.0","info":{"title":"Medtrics Connect API","version":"2026-10-27"},"tags":[{"name":"Scores","description":"Gradebook scores (PHI/FERPA). Legacy analog is /api/gradebook/scores/."}],"servers":[{"url":"https://sandbox.mymedtrics.com","description":"Client sandbox — shared demo tenant, X-Medtrics-Sandbox-Key or a sandbox API app"},{"url":"https://{client}.mymedtrics.com","description":"Your Medtrics instance","variables":{"client":{"default":"<client-name>","description":"The tenant subdomain Medtrics assigns to your institution"}}}],"security":[{"BearerToken":[]},{"SandboxApiKey":[]}],"components":{"securitySchemes":{"BearerToken":{"type":"http","scheme":"bearer"},"SandboxApiKey":{"type":"apiKey","in":"header","name":"X-Medtrics-Sandbox-Key"}},"parameters":{"ApiDateHeader":{"name":"Medtrics-API-Date","in":"header","required":true,"description":"API contract date. Use 2026-10-27 for this version. Contract dates select request behavior: rotation creates require explicit placement references from 2026-10-27; earlier accepted dates retain compatibility handling. Unknown dates return HTTP 400 with error.code unsupported_api_date.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"ScoreId":{"name":"scoreId","in":"path","required":true,"schema":{"type":"string"},"description":"Public ID of the score (score_ prefix). Backed by scores.id."}},"responses":{"ScoreItemResponse":{"description":"Single score record (PHI/FERPA).","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Score"}}}}}},"Unauthorized":{"description":"Missing or invalid credentials.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Credential lacks tenant visibility or required scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"NotFound":{"description":"Resource not found or outside tenant scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimited":{"description":"Request or API app rate limit exceeded.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InternalError":{"description":"Unexpected server error.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"headers":{"MedtricsRequestId":{"description":"Correlates all gateway logs for the request.","schema":{"type":"string"}},"MedtricsApiDate":{"description":"API contract date applied to the request.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Request limit for the current window.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Remaining requests in the current window.","schema":{"type":"string"}},"RateLimitReset":{"description":"Unix seconds when the current rate-limit window resets.","schema":{"type":"string"}}},"schemas":{"Score":{"type":"object","description":"A gradebook score scoped to the authenticated API app tenant (program→institution). Legacy analog is /api/gradebook/scores/ (Score). PHI/FERPA.","required":["id","legacy_id","learner_id","program_id","score_type_id","score_date","is_final","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ID of the score (score_ prefix). Backed by scores.id."},"legacy_id":{"type":["string","null"],"description":"Legacy SIS integer ID (as string) from etl_id_registry (source_entity_type='score'), minted on create."},"learner_id":{"type":"string","description":"Public ID of the learner (learner_ prefix). Backed by scores.learner_id."},"learner_legacy_id":{"type":["string","null"]},"program_id":{"type":"string","description":"Public ID of the program (prog_ prefix). Backed by scores.program_id."},"program_legacy_id":{"type":["string","null"]},"score_type_id":{"type":"string","description":"Public ID of the score type (stype_ prefix). Backed by scores.score_type_id."},"score_type_legacy_id":{"type":["string","null"]},"status_id":{"type":["string","null"],"description":"Public ID of the score status (sstat_ prefix). Backed by scores.status_id."},"block_schedule_id":{"type":["string","null"],"description":"Public ID of the clinical placement (rotsched_ prefix). Backed by scores.block_schedule_id (classic user_schedule)."},"block_schedule_legacy_id":{"type":["string","null"]},"score_date":{"type":"string","format":"date"},"numeric_score":{"type":["number","null"]},"letter_grade":{"type":["string","null"]},"percentile":{"type":["number","null"]},"is_final":{"type":"boolean"},"notes":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ErrorEnvelope":{"type":"object","required":["error"],"description":"Structured error envelope. error.code is the machine-readable discriminant. Typed detail schemas are provided for codes where structured data aids client remediation. Use the discriminator.mapping to select the correct variant schema; for all other codes see GenericApiError.\n","properties":{"error":{"anyOf":[{"$ref":"#/components/schemas/InvalidStatusError"},{"$ref":"#/components/schemas/InvalidWebhookEventsError"},{"$ref":"#/components/schemas/RateLimitedError"},{"$ref":"#/components/schemas/CursorResourceMismatchError"},{"$ref":"#/components/schemas/InvalidIdError"},{"$ref":"#/components/schemas/UnsupportedApiDateError"},{"$ref":"#/components/schemas/InactiveClientError"},{"$ref":"#/components/schemas/InvalidWebhookUrlError"},{"$ref":"#/components/schemas/GenericApiError"}],"discriminator":{"propertyName":"code","mapping":{"invalid_status":"#/components/schemas/InvalidStatusError","invalid_webhook_events":"#/components/schemas/InvalidWebhookEventsError","rate_limited":"#/components/schemas/RateLimitedError","cursor_resource_mismatch":"#/components/schemas/CursorResourceMismatchError","invalid_id":"#/components/schemas/InvalidIdError","unsupported_api_date":"#/components/schemas/UnsupportedApiDateError","inactive_client":"#/components/schemas/InactiveClientError","invalid_webhook_url":"#/components/schemas/InvalidWebhookUrlError"}}}}},"InvalidStatusError":{"description":"Returned when a status query parameter value is outside the allowed enum. HTTP 400. details.field identifies the parameter; details.allowed lists every accepted value.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_status"},"details":{"type":"object","required":["field","allowed"],"additionalProperties":false,"description":"Structured remediation data for invalid_status.","properties":{"field":{"type":"string","description":"Query parameter name that received the invalid value (e.g. enrollment_status, status).\n"},"allowed":{"type":"array","items":{"type":"string"},"description":"Full list of accepted values for the parameter."}}}}}]},"ApiErrorBase":{"type":"object","required":["code","message","request_id"],"description":"Common fields shared by every Connect API error response.","properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable error description."},"request_id":{"type":"string","description":"Request correlation ID. Include this value when reporting issues to support alongside the Medtrics-Request-ID response header.\n"}}},"InvalidWebhookEventsError":{"description":"Returned when event_types contains values not in the approved Connect API event list, or when event_types is empty. HTTP 400. details.unsupported_events lists the rejected entries (empty array when event_types was missing or entirely empty).\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_webhook_events"},"details":{"type":"object","required":["unsupported_events"],"additionalProperties":false,"description":"Structured remediation data for invalid_webhook_events.","properties":{"unsupported_events":{"type":"array","items":{"type":"string"},"description":"Event type strings that are not approved Connect API event names. Empty array indicates event_types was missing or contained only invalid entries.\n"}}}}}]},"RateLimitedError":{"description":"Returned when the request or API app rate limit is exceeded. HTTP 429. details.retry_after_seconds indicates the wait duration before retrying.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"rate_limited"},"details":{"type":"object","required":["retry_after_seconds"],"additionalProperties":false,"description":"Structured remediation data for rate_limited.","properties":{"retry_after_seconds":{"type":"integer","description":"Seconds to wait before retrying. Mirrors the Retry-After response header value.\n"}}}}}]},"CursorResourceMismatchError":{"description":"Returned when the cursor was issued for a different resource type than the endpoint being called. HTTP 400. details.expected_resource is the resource this endpoint serves; details.cursor_resource is what the cursor encodes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"cursor_resource_mismatch"},"details":{"type":"object","required":["expected_resource","cursor_resource"],"additionalProperties":false,"description":"Structured remediation data for cursor_resource_mismatch.","properties":{"expected_resource":{"type":"string","description":"Resource type this endpoint serves (e.g. programs, learners)."},"cursor_resource":{"type":"string","description":"Resource type encoded in the submitted cursor."}}}}}]},"InvalidIdError":{"description":"Returned when a path parameter public ID does not match the expected prefix for the resource. HTTP 400. details.field is the parameter name; details.expected_prefix is the required ID prefix.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_id"},"details":{"type":"object","required":["field","expected_prefix"],"additionalProperties":false,"description":"Structured remediation data for invalid_id.","properties":{"field":{"type":"string","description":"Path or query parameter name that received the invalid ID."},"expected_prefix":{"type":"string","description":"Required ID prefix for this parameter."}}}}}]},"UnsupportedApiDateError":{"description":"Returned when the Medtrics-API-Date header is missing, malformed (not YYYY-MM-DD), or not a supported contract date. HTTP 400. details.supported_dates lists all accepted values. details.reason is one of \"missing\", \"malformed\", or \"not_supported\".\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"unsupported_api_date"},"details":{"type":"object","required":["reason","supported_dates"],"additionalProperties":false,"description":"Structured remediation data for unsupported_api_date.","properties":{"reason":{"type":"string","enum":["missing","malformed","not_supported"],"description":"Specific cause: \"missing\" when the header is absent, \"malformed\" when the value is not YYYY-MM-DD format, \"not_supported\" when the format is valid but the date is not a known contract date.\n"},"supported_dates":{"type":"array","items":{"type":"string"},"description":"All accepted Medtrics-API-Date values."}}}}}]},"InactiveClientError":{"description":"Returned when the authenticated API client is revoked, expired, deleted, or in a non-active status. HTTP 403. No structured details beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"inactive_client"}}}]},"InvalidWebhookUrlError":{"description":"Returned when target_url fails HTTPS validation or is otherwise rejected. HTTP 422. No structured details field beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"invalid_webhook_url"}}}]},"GenericApiError":{"description":"Catch-all error variant for codes that carry no structured remediation data (invalid_cursor, not_found, invalid_credentials, scope_not_allowed, invalid_webhook_tolerance, internal_error, and any future codes not covered by a typed variant in the discriminator.mapping). details is absent or empty for these codes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"details":{"type":"object","additionalProperties":true,"description":"Absent or empty for most generic error codes."}}}]}}},"paths":{"/connect/scores/{scoreId}":{"get":{"operationId":"getScore","tags":["Scores"],"summary":"Get a score.","description":"Returns one score when it belongs to the authenticated API app tenant. Requires scores:read scope. PHI/FERPA.","parameters":[{"$ref":"#/components/parameters/ApiDateHeader"},{"$ref":"#/components/parameters/ScoreId"}],"responses":{"200":{"$ref":"#/components/responses/ScoreItemResponse"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## List score types.

> Returns cursor-paged gradebook score types (vocabulary) usable within the tenant. Requires scores:read scope.

```json
{"openapi":"3.1.0","info":{"title":"Medtrics Connect API","version":"2026-10-27"},"tags":[{"name":"Scores","description":"Gradebook scores (PHI/FERPA). Legacy analog is /api/gradebook/scores/."}],"servers":[{"url":"https://sandbox.mymedtrics.com","description":"Client sandbox — shared demo tenant, X-Medtrics-Sandbox-Key or a sandbox API app"},{"url":"https://{client}.mymedtrics.com","description":"Your Medtrics instance","variables":{"client":{"default":"<client-name>","description":"The tenant subdomain Medtrics assigns to your institution"}}}],"security":[{"BearerToken":[]},{"SandboxApiKey":[]}],"components":{"securitySchemes":{"BearerToken":{"type":"http","scheme":"bearer"},"SandboxApiKey":{"type":"apiKey","in":"header","name":"X-Medtrics-Sandbox-Key"}},"parameters":{"ApiDateHeader":{"name":"Medtrics-API-Date","in":"header","required":true,"description":"API contract date. Use 2026-10-27 for this version. Contract dates select request behavior: rotation creates require explicit placement references from 2026-10-27; earlier accepted dates retain compatibility handling. Unknown dates return HTTP 400 with error.code unsupported_api_date.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"Limit":{"name":"limit","in":"query","required":false,"description":"Maximum number of records to return per page. The server may return fewer rows than requested. Values above the maximum (100) are silently clamped to 100. Values below the minimum (1) are silently clamped to 1. The effective value after clamping is always returned in pagination.limit so callers can detect that they hit the gateway ceiling. Per-client max_page_size overrides are documented as a tenant-configurable lower cap that never raises the public ceiling.\n","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"Cursor":{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},"ProgramIdQuery":{"name":"program_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by program public ID (prog_ prefix). Returns only records belonging to this program."},"LegacyIdQuery":{"name":"legacy_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by legacy source ID from etl_id_registry. Useful for bridge lookups."}},"responses":{"ScoreTypeListResponse":{"description":"Cursor-paged score type records.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScoreType"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"BadRequest":{"description":"Invalid request parameters.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"Missing or invalid credentials.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Credential lacks tenant visibility or required scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimited":{"description":"Request or API app rate limit exceeded.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InternalError":{"description":"Unexpected server error.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"headers":{"MedtricsRequestId":{"description":"Correlates all gateway logs for the request.","schema":{"type":"string"}},"MedtricsApiDate":{"description":"API contract date applied to the request.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Request limit for the current window.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Remaining requests in the current window.","schema":{"type":"string"}},"RateLimitReset":{"description":"Unix seconds when the current rate-limit window resets.","schema":{"type":"string"}}},"schemas":{"ScoreType":{"type":"object","description":"A gradebook score type (vocabulary) usable within a program. Read-only via the Connect API.","required":["id","legacy_id","name","value_mode","is_active","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ID of the score type (stype_ prefix). Backed by score_types.id."},"legacy_id":{"type":["string","null"],"description":"Legacy SIS integer ID (as string) from etl_id_registry (source_entity_type='score_type')."},"name":{"type":"string"},"code":{"type":["string","null"]},"value_mode":{"type":"string","enum":["numeric_status","status_only"]},"program_id":{"type":["string","null"],"description":"Public ID of the owning program (prog_ prefix); null for global/shared types."},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Pagination":{"type":"object","description":"Cursor pagination envelope. Exposes only limit and next_cursor. Count fields (approximate_total, total_count_exact, or any equivalent) are intentionally absent and reserved for future Medtrics-API-Date additions once a concrete partner use case justifies a count strategy per route. pagination.limit is the effective page size after server-side clamp, not the value the client requested.","required":["limit","next_cursor"],"properties":{"limit":{"type":"integer","description":"Effective page size after server-side clamping. Compare to your requested limit to detect ceiling enforcement."},"next_cursor":{"type":["string","null"],"description":"Opaque keyset cursor. Pass as the cursor query parameter on the next request. null when no more pages exist."}}},"ErrorEnvelope":{"type":"object","required":["error"],"description":"Structured error envelope. error.code is the machine-readable discriminant. Typed detail schemas are provided for codes where structured data aids client remediation. Use the discriminator.mapping to select the correct variant schema; for all other codes see GenericApiError.\n","properties":{"error":{"anyOf":[{"$ref":"#/components/schemas/InvalidStatusError"},{"$ref":"#/components/schemas/InvalidWebhookEventsError"},{"$ref":"#/components/schemas/RateLimitedError"},{"$ref":"#/components/schemas/CursorResourceMismatchError"},{"$ref":"#/components/schemas/InvalidIdError"},{"$ref":"#/components/schemas/UnsupportedApiDateError"},{"$ref":"#/components/schemas/InactiveClientError"},{"$ref":"#/components/schemas/InvalidWebhookUrlError"},{"$ref":"#/components/schemas/GenericApiError"}],"discriminator":{"propertyName":"code","mapping":{"invalid_status":"#/components/schemas/InvalidStatusError","invalid_webhook_events":"#/components/schemas/InvalidWebhookEventsError","rate_limited":"#/components/schemas/RateLimitedError","cursor_resource_mismatch":"#/components/schemas/CursorResourceMismatchError","invalid_id":"#/components/schemas/InvalidIdError","unsupported_api_date":"#/components/schemas/UnsupportedApiDateError","inactive_client":"#/components/schemas/InactiveClientError","invalid_webhook_url":"#/components/schemas/InvalidWebhookUrlError"}}}}},"InvalidStatusError":{"description":"Returned when a status query parameter value is outside the allowed enum. HTTP 400. details.field identifies the parameter; details.allowed lists every accepted value.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_status"},"details":{"type":"object","required":["field","allowed"],"additionalProperties":false,"description":"Structured remediation data for invalid_status.","properties":{"field":{"type":"string","description":"Query parameter name that received the invalid value (e.g. enrollment_status, status).\n"},"allowed":{"type":"array","items":{"type":"string"},"description":"Full list of accepted values for the parameter."}}}}}]},"ApiErrorBase":{"type":"object","required":["code","message","request_id"],"description":"Common fields shared by every Connect API error response.","properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable error description."},"request_id":{"type":"string","description":"Request correlation ID. Include this value when reporting issues to support alongside the Medtrics-Request-ID response header.\n"}}},"InvalidWebhookEventsError":{"description":"Returned when event_types contains values not in the approved Connect API event list, or when event_types is empty. HTTP 400. details.unsupported_events lists the rejected entries (empty array when event_types was missing or entirely empty).\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_webhook_events"},"details":{"type":"object","required":["unsupported_events"],"additionalProperties":false,"description":"Structured remediation data for invalid_webhook_events.","properties":{"unsupported_events":{"type":"array","items":{"type":"string"},"description":"Event type strings that are not approved Connect API event names. Empty array indicates event_types was missing or contained only invalid entries.\n"}}}}}]},"RateLimitedError":{"description":"Returned when the request or API app rate limit is exceeded. HTTP 429. details.retry_after_seconds indicates the wait duration before retrying.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"rate_limited"},"details":{"type":"object","required":["retry_after_seconds"],"additionalProperties":false,"description":"Structured remediation data for rate_limited.","properties":{"retry_after_seconds":{"type":"integer","description":"Seconds to wait before retrying. Mirrors the Retry-After response header value.\n"}}}}}]},"CursorResourceMismatchError":{"description":"Returned when the cursor was issued for a different resource type than the endpoint being called. HTTP 400. details.expected_resource is the resource this endpoint serves; details.cursor_resource is what the cursor encodes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"cursor_resource_mismatch"},"details":{"type":"object","required":["expected_resource","cursor_resource"],"additionalProperties":false,"description":"Structured remediation data for cursor_resource_mismatch.","properties":{"expected_resource":{"type":"string","description":"Resource type this endpoint serves (e.g. programs, learners)."},"cursor_resource":{"type":"string","description":"Resource type encoded in the submitted cursor."}}}}}]},"InvalidIdError":{"description":"Returned when a path parameter public ID does not match the expected prefix for the resource. HTTP 400. details.field is the parameter name; details.expected_prefix is the required ID prefix.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_id"},"details":{"type":"object","required":["field","expected_prefix"],"additionalProperties":false,"description":"Structured remediation data for invalid_id.","properties":{"field":{"type":"string","description":"Path or query parameter name that received the invalid ID."},"expected_prefix":{"type":"string","description":"Required ID prefix for this parameter."}}}}}]},"UnsupportedApiDateError":{"description":"Returned when the Medtrics-API-Date header is missing, malformed (not YYYY-MM-DD), or not a supported contract date. HTTP 400. details.supported_dates lists all accepted values. details.reason is one of \"missing\", \"malformed\", or \"not_supported\".\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"unsupported_api_date"},"details":{"type":"object","required":["reason","supported_dates"],"additionalProperties":false,"description":"Structured remediation data for unsupported_api_date.","properties":{"reason":{"type":"string","enum":["missing","malformed","not_supported"],"description":"Specific cause: \"missing\" when the header is absent, \"malformed\" when the value is not YYYY-MM-DD format, \"not_supported\" when the format is valid but the date is not a known contract date.\n"},"supported_dates":{"type":"array","items":{"type":"string"},"description":"All accepted Medtrics-API-Date values."}}}}}]},"InactiveClientError":{"description":"Returned when the authenticated API client is revoked, expired, deleted, or in a non-active status. HTTP 403. No structured details beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"inactive_client"}}}]},"InvalidWebhookUrlError":{"description":"Returned when target_url fails HTTPS validation or is otherwise rejected. HTTP 422. No structured details field beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"invalid_webhook_url"}}}]},"GenericApiError":{"description":"Catch-all error variant for codes that carry no structured remediation data (invalid_cursor, not_found, invalid_credentials, scope_not_allowed, invalid_webhook_tolerance, internal_error, and any future codes not covered by a typed variant in the discriminator.mapping). details is absent or empty for these codes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"details":{"type":"object","additionalProperties":true,"description":"Absent or empty for most generic error codes."}}}]}}},"paths":{"/connect/score-types":{"get":{"operationId":"listScoreTypes","tags":["Scores"],"summary":"List score types.","description":"Returns cursor-paged gradebook score types (vocabulary) usable within the tenant. Requires scores:read scope.","parameters":[{"$ref":"#/components/parameters/ApiDateHeader"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/ProgramIdQuery"},{"$ref":"#/components/parameters/LegacyIdQuery"}],"responses":{"200":{"$ref":"#/components/responses/ScoreTypeListResponse"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Get a score type.

> Returns one score type when visible to the authenticated API app tenant. Requires scores:read scope.

```json
{"openapi":"3.1.0","info":{"title":"Medtrics Connect API","version":"2026-10-27"},"tags":[{"name":"Scores","description":"Gradebook scores (PHI/FERPA). Legacy analog is /api/gradebook/scores/."}],"servers":[{"url":"https://sandbox.mymedtrics.com","description":"Client sandbox — shared demo tenant, X-Medtrics-Sandbox-Key or a sandbox API app"},{"url":"https://{client}.mymedtrics.com","description":"Your Medtrics instance","variables":{"client":{"default":"<client-name>","description":"The tenant subdomain Medtrics assigns to your institution"}}}],"security":[{"BearerToken":[]},{"SandboxApiKey":[]}],"components":{"securitySchemes":{"BearerToken":{"type":"http","scheme":"bearer"},"SandboxApiKey":{"type":"apiKey","in":"header","name":"X-Medtrics-Sandbox-Key"}},"parameters":{"ApiDateHeader":{"name":"Medtrics-API-Date","in":"header","required":true,"description":"API contract date. Use 2026-10-27 for this version. Contract dates select request behavior: rotation creates require explicit placement references from 2026-10-27; earlier accepted dates retain compatibility handling. Unknown dates return HTTP 400 with error.code unsupported_api_date.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"ScoreTypeId":{"name":"scoreTypeId","in":"path","required":true,"schema":{"type":"string"},"description":"Public ID of the score type (stype_ prefix). Backed by score_types.id."}},"responses":{"ScoreTypeItemResponse":{"description":"Single score type record.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ScoreType"}}}}}},"Unauthorized":{"description":"Missing or invalid credentials.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Credential lacks tenant visibility or required scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"NotFound":{"description":"Resource not found or outside tenant scope.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimited":{"description":"Request or API app rate limit exceeded.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InternalError":{"description":"Unexpected server error.","headers":{"Medtrics-Request-ID":{"$ref":"#/components/headers/MedtricsRequestId"},"Medtrics-API-Date":{"$ref":"#/components/headers/MedtricsApiDate"},"Medtrics-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"Medtrics-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Medtrics-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"headers":{"MedtricsRequestId":{"description":"Correlates all gateway logs for the request.","schema":{"type":"string"}},"MedtricsApiDate":{"description":"API contract date applied to the request.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Request limit for the current window.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Remaining requests in the current window.","schema":{"type":"string"}},"RateLimitReset":{"description":"Unix seconds when the current rate-limit window resets.","schema":{"type":"string"}}},"schemas":{"ScoreType":{"type":"object","description":"A gradebook score type (vocabulary) usable within a program. Read-only via the Connect API.","required":["id","legacy_id","name","value_mode","is_active","created_at","updated_at"],"properties":{"id":{"type":"string","description":"Public ID of the score type (stype_ prefix). Backed by score_types.id."},"legacy_id":{"type":["string","null"],"description":"Legacy SIS integer ID (as string) from etl_id_registry (source_entity_type='score_type')."},"name":{"type":"string"},"code":{"type":["string","null"]},"value_mode":{"type":"string","enum":["numeric_status","status_only"]},"program_id":{"type":["string","null"],"description":"Public ID of the owning program (prog_ prefix); null for global/shared types."},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ErrorEnvelope":{"type":"object","required":["error"],"description":"Structured error envelope. error.code is the machine-readable discriminant. Typed detail schemas are provided for codes where structured data aids client remediation. Use the discriminator.mapping to select the correct variant schema; for all other codes see GenericApiError.\n","properties":{"error":{"anyOf":[{"$ref":"#/components/schemas/InvalidStatusError"},{"$ref":"#/components/schemas/InvalidWebhookEventsError"},{"$ref":"#/components/schemas/RateLimitedError"},{"$ref":"#/components/schemas/CursorResourceMismatchError"},{"$ref":"#/components/schemas/InvalidIdError"},{"$ref":"#/components/schemas/UnsupportedApiDateError"},{"$ref":"#/components/schemas/InactiveClientError"},{"$ref":"#/components/schemas/InvalidWebhookUrlError"},{"$ref":"#/components/schemas/GenericApiError"}],"discriminator":{"propertyName":"code","mapping":{"invalid_status":"#/components/schemas/InvalidStatusError","invalid_webhook_events":"#/components/schemas/InvalidWebhookEventsError","rate_limited":"#/components/schemas/RateLimitedError","cursor_resource_mismatch":"#/components/schemas/CursorResourceMismatchError","invalid_id":"#/components/schemas/InvalidIdError","unsupported_api_date":"#/components/schemas/UnsupportedApiDateError","inactive_client":"#/components/schemas/InactiveClientError","invalid_webhook_url":"#/components/schemas/InvalidWebhookUrlError"}}}}},"InvalidStatusError":{"description":"Returned when a status query parameter value is outside the allowed enum. HTTP 400. details.field identifies the parameter; details.allowed lists every accepted value.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_status"},"details":{"type":"object","required":["field","allowed"],"additionalProperties":false,"description":"Structured remediation data for invalid_status.","properties":{"field":{"type":"string","description":"Query parameter name that received the invalid value (e.g. enrollment_status, status).\n"},"allowed":{"type":"array","items":{"type":"string"},"description":"Full list of accepted values for the parameter."}}}}}]},"ApiErrorBase":{"type":"object","required":["code","message","request_id"],"description":"Common fields shared by every Connect API error response.","properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable error description."},"request_id":{"type":"string","description":"Request correlation ID. Include this value when reporting issues to support alongside the Medtrics-Request-ID response header.\n"}}},"InvalidWebhookEventsError":{"description":"Returned when event_types contains values not in the approved Connect API event list, or when event_types is empty. HTTP 400. details.unsupported_events lists the rejected entries (empty array when event_types was missing or entirely empty).\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_webhook_events"},"details":{"type":"object","required":["unsupported_events"],"additionalProperties":false,"description":"Structured remediation data for invalid_webhook_events.","properties":{"unsupported_events":{"type":"array","items":{"type":"string"},"description":"Event type strings that are not approved Connect API event names. Empty array indicates event_types was missing or contained only invalid entries.\n"}}}}}]},"RateLimitedError":{"description":"Returned when the request or API app rate limit is exceeded. HTTP 429. details.retry_after_seconds indicates the wait duration before retrying.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"rate_limited"},"details":{"type":"object","required":["retry_after_seconds"],"additionalProperties":false,"description":"Structured remediation data for rate_limited.","properties":{"retry_after_seconds":{"type":"integer","description":"Seconds to wait before retrying. Mirrors the Retry-After response header value.\n"}}}}}]},"CursorResourceMismatchError":{"description":"Returned when the cursor was issued for a different resource type than the endpoint being called. HTTP 400. details.expected_resource is the resource this endpoint serves; details.cursor_resource is what the cursor encodes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"cursor_resource_mismatch"},"details":{"type":"object","required":["expected_resource","cursor_resource"],"additionalProperties":false,"description":"Structured remediation data for cursor_resource_mismatch.","properties":{"expected_resource":{"type":"string","description":"Resource type this endpoint serves (e.g. programs, learners)."},"cursor_resource":{"type":"string","description":"Resource type encoded in the submitted cursor."}}}}}]},"InvalidIdError":{"description":"Returned when a path parameter public ID does not match the expected prefix for the resource. HTTP 400. details.field is the parameter name; details.expected_prefix is the required ID prefix.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"invalid_id"},"details":{"type":"object","required":["field","expected_prefix"],"additionalProperties":false,"description":"Structured remediation data for invalid_id.","properties":{"field":{"type":"string","description":"Path or query parameter name that received the invalid ID."},"expected_prefix":{"type":"string","description":"Required ID prefix for this parameter."}}}}}]},"UnsupportedApiDateError":{"description":"Returned when the Medtrics-API-Date header is missing, malformed (not YYYY-MM-DD), or not a supported contract date. HTTP 400. details.supported_dates lists all accepted values. details.reason is one of \"missing\", \"malformed\", or \"not_supported\".\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","required":["details"],"properties":{"code":{"type":"string","const":"unsupported_api_date"},"details":{"type":"object","required":["reason","supported_dates"],"additionalProperties":false,"description":"Structured remediation data for unsupported_api_date.","properties":{"reason":{"type":"string","enum":["missing","malformed","not_supported"],"description":"Specific cause: \"missing\" when the header is absent, \"malformed\" when the value is not YYYY-MM-DD format, \"not_supported\" when the format is valid but the date is not a known contract date.\n"},"supported_dates":{"type":"array","items":{"type":"string"},"description":"All accepted Medtrics-API-Date values."}}}}}]},"InactiveClientError":{"description":"Returned when the authenticated API client is revoked, expired, deleted, or in a non-active status. HTTP 403. No structured details beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"inactive_client"}}}]},"InvalidWebhookUrlError":{"description":"Returned when target_url fails HTTPS validation or is otherwise rejected. HTTP 422. No structured details field beyond the human-readable message.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"code":{"type":"string","const":"invalid_webhook_url"}}}]},"GenericApiError":{"description":"Catch-all error variant for codes that carry no structured remediation data (invalid_cursor, not_found, invalid_credentials, scope_not_allowed, invalid_webhook_tolerance, internal_error, and any future codes not covered by a typed variant in the discriminator.mapping). details is absent or empty for these codes.\n","allOf":[{"$ref":"#/components/schemas/ApiErrorBase"},{"type":"object","properties":{"details":{"type":"object","additionalProperties":true,"description":"Absent or empty for most generic error codes."}}}]}}},"paths":{"/connect/score-types/{scoreTypeId}":{"get":{"operationId":"getScoreType","tags":["Scores"],"summary":"Get a score type.","description":"Returns one score type when visible to the authenticated API app tenant. Requires scores:read scope.","parameters":[{"$ref":"#/components/parameters/ApiDateHeader"},{"$ref":"#/components/parameters/ScoreTypeId"}],"responses":{"200":{"$ref":"#/components/responses/ScoreTypeItemResponse"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.mymedtrics.com/api-reference/connect-api/scores.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
