certifications

21 endpoints.

GET/api/certifications Bearer token

List certification types

Lists the certification types the caller can read, newest first, with cursor pagination. Requires certifications:read in scope; rows outside the caller's scope are simply absent.

Parameters

NameInTypeRequiredDescription
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).
departmentquerystringnoDepartment UUID id or slug, resolved within org (which is then required).
include_archivedquerystringnoInclude archived rows. Defaults to false.
limitqueryintegernoPage size, 1-200. Defaults to 50.
cursorquerystringnoOpaque cursor from a previous page's next_cursor.

Responses

StatusDescriptionBody
200One page of certification types, and the cursor for the next.CertificationTypeList
400A filter did not resolve, or the cursor is malformed.ErrorResponse
401The access token is missing or invalid.ErrorResponse
500The database could not be read.ErrorResponse
POST/api/certifications Bearer token

Create a certification type

Creates a certification type owned by an organization, or by one department within it, tagged with any number of subject matters of the same organization. Requires certifications:write over the owner.

Request body

application/jsonrequiredCreateCertificationTypeRequest
FieldTypeRequiredDescription
owner_organization_idstring (uuid)yes

Organization the certification type belongs to. Always required.

owner_department_idstring (uuid)no

Omit for a type owned by the organization directly.

subject_matter_idsarray of string (uuid)no

Subject matters of the same organization to tag the type with; records filed under any of them satisfy its record-based rules. Omit for an untagged type; the set can be replaced later through PUT /certifications/{cert_id}/subjects.

at most 50 items

slugstringyes

Unique within the organization. Slugs are lowercase letters and digits in words separated by single hyphens, like forklift-operator.

1–100 characters · matches ^[a-z0-9]+(-[a-z0-9]+)*$

namestringyes

1–200 characters

descriptionstringno

Omit or send empty for no description.

at most 2000 characters

description_markdownstringno

Omit or send empty for no long-form markdown description.

at most 50000 characters

awarding_modestringyes

automatic: the user claims the certification themselves once every rule is satisfied. approval: the user requests it and a permission holder decides.

one of "automatic" | "approval"

Responses

StatusDescriptionBody
201The created certification type.CertificationType
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold certifications:write over the owner.ErrorResponse
404The organization, the department within it, or a subject matter does not exist (or a subject belongs to another organization).ErrorResponse
409The organization already has a certification type with that slug.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
GET/api/certifications/{cert_id}/attachments/{attachment_id}/download Bearer token

Get a download URL for a certification type attachment

Issues a short-lived presigned GET for the private attachment. Readable by anyone an unexpired role grant requires the type of, and by holders of certifications:read over its owner.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
attachment_idpathstring (uuid)yesUUID id of the attachment.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Responses

StatusDescriptionBody
200Where to fetch the file from, for the next five minutes.DownloadTicket
401The access token is missing or invalid.ErrorResponse
404No visible certification type matches the path, or it has no such attachment.ErrorResponse
500The download URL could not be signed.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
POST/api/certifications/{cert_id}/attachment-uploads Bearer token

Request an upload URL for a certification type attachment

Issues a presigned URL to PUT one file of any type straight to private blob storage, scoped to this certification type, the declared content type and a 500 MB ceiling. Attach it with POST /certifications/{cert_id}/attachments and the returned pathname afterwards. Requires certifications:write.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonrequiredCreateDescriptionUploadRequest
FieldTypeRequiredDescription
file_namestringyes

1–300 characters

content_typestringyes

The file's content type; any type is allowed, but the upload pins this one.

1–200 characters

size_bytesintegeryes

maximum 524288000

Responses

StatusDescriptionBody
201Where to PUT the file, and the pathname the attachment will point at.DescriptionUploadTicket
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this certification type but lacks certifications:write.ErrorResponse
404No visible certification type matches the path.ErrorResponse
500The upload URL could not be signed.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
POST/api/certifications/{cert_id}/attachments Bearer token

Attach an uploaded file to a certification type

Creates the attachment at the end of the authored order, pointing at a pathname an upload ticket was issued for (after PUTting the file there). The content type is read back from the store, never from the request. Requires certifications:write.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonrequiredCreateDescriptionAttachmentRequest
FieldTypeRequiredDescription
pathnamestringyes

The pathname an upload ticket was issued for, after PUTting the file.

at least 1 character

file_namestringyes

1–300 characters

labelstringno

Omit or send empty to show the file name instead.

at most 200 characters

prefer_inline_displaybooleanno

Omit to show the file on the page where its type allows it. Send false for a file meant to be downloaded and worked on locally — a blank form, a spreadsheet — so it renders as a download instead of an inline viewer.

Responses

StatusDescriptionBody
201The created attachment.DescriptionAttachment
400The body failed validation, or the pathname was not uploaded.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this certification type but lacks certifications:write.ErrorResponse
404No visible certification type matches the path.ErrorResponse
409That upload is already attached.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
PATCH/api/certifications/{cert_id}/attachments/{attachment_id} Bearer token

Relabel or reorder a certification type attachment

Changes the attachment's label (null or empty clears it back to the file name), whether it shows on the page or downloads only, or its slot in the authored order. Requires certifications:write.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
attachment_idpathstring (uuid)yesUUID id of the attachment.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonrequiredUpdateDescriptionAttachmentRequest
FieldTypeRequiredDescription
labelstring | nullno

Send null or empty to clear the label back to the file name.

at most 200 characters

positionintegerno

New slot in the authored order.

minimum 0

prefer_inline_displaybooleanno

Switches the file between showing on the page and being offered as a download only.

Responses

StatusDescriptionBody
200The updated attachment.DescriptionAttachment
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this certification type but lacks certifications:write.ErrorResponse
404No visible certification type matches the path, or it has no such attachment.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
DELETE/api/certifications/{cert_id}/attachments/{attachment_id} Bearer token

Delete a certification type attachment

Removes the attachment; the blob it pointed at is deleted best-effort. Requires certifications:write.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
attachment_idpathstring (uuid)yesUUID id of the attachment.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Responses

StatusDescriptionBody
204The attachment is gone.—
401The access token is missing or invalid.ErrorResponse
403The caller can read this certification type but lacks certifications:write.ErrorResponse
404No visible certification type matches the path, or it has no such attachment.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
PUT/api/certifications/{cert_id}/subjects Bearer token

Replace a certification type's subject tags

Sets the complete set of subject matters whose records and evidence satisfy the type's record-based rules — a record filed under any of them counts. Awards already given stand; only evaluation from now on follows the new set. Subjects of the type's own organization only. A tag one of the type's rules is narrowed to cannot be removed until that rule is deleted or widened. Requires certifications:write over the type's owner.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonrequiredSetCertificationTypeSubjectsRequest
FieldTypeRequiredDescription
subject_matter_idsarray of string (uuid)yes

Replaces the type's subject-matter tags; send an empty array to clear them.

at most 50 items

Responses

StatusDescriptionBody
200The type's subjects after the change, alphabetically.array of CertificationTypeSubject
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:write.ErrorResponse
404No visible certification type has that id or slug, or a subject is not the organization's own.ErrorResponse
409A rule of the type is narrowed to a tag the new set drops.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
GET/api/certifications/{cert_id}/permanent-deletion Bearer token

Preview permanently deleting a certification type

Counts everything DELETE on this path would remove: awards (people lose the certification, past ones included), pending requests, sign-offs, due dates, proof rules, role requirement links, pathway level memberships and attachments. Nothing is changed. Requires certifications:delete — a grant separate from certifications:write, which only archives.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Responses

StatusDescriptionBody
200What the deletion would take with it.DeletionImpact
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:delete.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
500The database could not be read.ErrorResponse
DELETE/api/certifications/{cert_id}/permanent-deletion Bearer token

Permanently delete a certification type

Hard-deletes the type and everything that depends on it — unlike DELETE /certifications/{cert_id}, which only archives. Every award of the type is deleted, so current holders lose the certification and past certifications vanish from every history; pending requests, sign-offs, due dates, rules, role requirement links, pathway level memberships and attachments go with it. Irreversible. Preview the cost with GET first. Requires certifications:delete — a grant separate from certifications:write, which only archives.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Responses

StatusDescriptionBody
204The certification type and its dependent rows are gone.—
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:delete.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
POST/api/certifications/{cert_id}/duplicate Bearer token

Duplicate a certification type

Creates a copy of a certification type: its descriptions, awarding mode, subject tags and every proof rule, and its description attachments — each file copied in the store, so deleting either type later leaves the other's files alone. Role requirements, awards, requests, due dates and sign-offs stay with the original. The copy is named after the original with " (copy)" appended and takes the first free -copy slug unless name and slug are given. Requires certifications:write over the type's owner.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonoptionalDuplicateCertificationTypeRequest
FieldTypeRequiredDescription
namestringno

The copy's name; omit for the original's with " (copy)" appended.

1–200 characters

slugstringno

The copy's slug, unique within the organization; omit for the first free `-copy`, `-copy-2`… of the original's. Slugs are lowercase letters and digits in words separated by single hyphens, like forklift-operator.

1–100 characters · matches ^[a-z0-9]+(-[a-z0-9]+)*$

Responses

StatusDescriptionBody
201The copy, with its rules and attachments.CertificationTypeDetail
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:write.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
409The organization already has a certification type with the requested slug, or another copy took the generated one first — retry.ErrorResponse
500The database could not be reached, or the write or a file copy failed.ErrorResponse
503The type has attachments and file storage is not configured here.ErrorResponse
GET/api/certifications/{cert_id} Bearer token

Get a certification type

Returns one certification type with its proof rules, by UUID id or by slug resolved within ?org=. Requires certifications:read over its owner.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Responses

StatusDescriptionBody
200The certification type and its rules.CertificationTypeDetail
401The access token is missing or invalid.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
500The database could not be read.ErrorResponse
PATCH/api/certifications/{cert_id} Bearer token

Update a certification type

Changes a certification type's slug, name, description or awarding mode. The subject tags are replaced as a set through PUT /certifications/{cert_id}/subjects. Requires certifications:write.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonrequiredUpdateCertificationTypeRequest
FieldTypeRequiredDescription
slugstringno

1–100 characters · matches ^[a-z0-9]+(-[a-z0-9]+)*$

namestringno

1–200 characters

descriptionstring | nullno

Send null to clear the description.

at most 2000 characters

description_markdownstring | nullno

Send null to clear the long-form markdown description.

at most 50000 characters

awarding_modestringno

Changing the mode does not touch existing requests: pending requests on a now-automatic type remain decidable and withdrawable.

one of "automatic" | "approval"

Responses

StatusDescriptionBody
200The updated certification type.CertificationType
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:write.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
409The organization already has a certification type with that slug.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
DELETE/api/certifications/{cert_id} Bearer token

Archive a certification type

Soft-deletes a certification type by setting archived_at. Archived types stop being evaluated as requirements; awards already given stay readable. Requires certifications:write.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Responses

StatusDescriptionBody
200The archived certification type.CertificationType
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:write.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
POST/api/certifications/{cert_id}/rules Bearer token

Add a proof rule

Adds one proof rule to a certification type; all rules of a type must be satisfied at once for it to be awardable. Note that date_range evidence counts its full elapsed wall-clock time towards subject_hours rules, so size thresholds accordingly. A subject_hours or subject_record_count rule counts records on every subject tag of the type unless subject_matter_id narrows it to one of them. A scorm_course_complete rule is satisfied by an attempt of the hosted course reported complete without an explicit failed verdict; a job_aid_viewed rule by an open of the job aid's page. Requires certifications:write over the type's owner.

Parameters

NameInTypeRequiredDescription
cert_idpathstringyesUUID id, or a slug resolved within the organization given by the org query parameter.
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).

Request body

application/jsonrequiredCreateCertificationRuleRequest
FieldTypeRequiredDescription
rule_kindstringyes

subject_hours: evidenced hours on the type's subjects (or on subject_matter_id alone) must reach threshold_hours. subject_record_count: completed records on the subjects (or on subject_matter_id alone) must reach threshold_count. evidence_document: a completed record on the subject must carry evidence of evidence_type (a pass_fail row counts only when it records a pass). manual_sign_off: a permission holder must record a sign-off for the rule. quiz_pass: the user must have a passing attempt of the quiz named by quiz_id. external_course_pass: the user must have a passing grade of the external LMS course named by external_course_id. scorm_course_complete: the user must have completed the hosted SCORM course named by scorm_course_id. job_aid_viewed: the user must have opened the job aid named by job_aid_id.

one of "subject_hours" | "subject_record_count" | "evidence_document" | "manual_sign_off" | "quiz_pass" | "external_course_pass" | "scorm_course_complete" | "job_aid_viewed"

labelstringno

Human label shown wherever the rule's progress is, e.g. "20 simulator hours".

1–200 characters

threshold_hoursnumberno

Hours required, for subject_hours rules. Counted from quantity evidence in hours or minutes, plus the elapsed time of date_range evidence.

threshold_countintegerno

Completed records required, for subject_record_count rules.

evidence_typestringno

Evidence type that must be present, for evidence_document rules. A pass_fail rule is met only by a row recording a pass.

one of "score" | "date_range" | "quantity" | "url" | "file" | "pass_fail" | "note"

quiz_idstring (uuid)no

Quiz that must be passed, for quiz_pass rules. A quiz of the type's own organization.

external_course_idstring (uuid)no

Catalogue id of the external LMS course that must be passed, for external_course_pass rules. A course of the type's own organization. Passing is decided by the course: its passing_score when set, the imported passed flag otherwise.

scorm_course_idstring (uuid)no

Hosted SCORM course that must be completed, for scorm_course_complete rules. A course of the type's own organization. Completion is what the course's completion records count: an attempt the module reported complete without an explicit failed verdict.

job_aid_idstring (uuid)no

Job aid that must be viewed, for job_aid_viewed rules. An aid of the type's own organization. Viewing is an open of the aid's page (POST /job-aids/{job_aid_id}/views, which the page does on every load), inside the current recertification window; opens of its individual files do not count.

subject_matter_idstring (uuid)no

Narrows a subject_hours or subject_record_count rule to one subject: only records filed under it count. Must be one of the type's own subject tags; omit to count records on every tag of the type.

Responses

StatusDescriptionBody
201The created rule.CertificationRule
400The request body failed validation, or a reference (quiz, course, subject tag) does not belong to the type.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this type but does not hold certifications:write.ErrorResponse
404No visible certification type has that id or slug.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
PATCH/api/certification-rules/{rule_id} Bearer token

Update a proof rule

Changes a rule's label or configuration. The rule kind is immutable — delete and recreate a rule that should mean something else. Requires certifications:write over the type's owner. Progress is recomputed retroactively; award history is unaffected.

Parameters

NameInTypeRequiredDescription
rule_idpathstring (uuid)yesUUID id of the proof rule.

Request body

application/jsonrequiredUpdateCertificationRuleRequest
FieldTypeRequiredDescription
labelstring | nullno

Send null to clear the label.

1–200 characters

threshold_hoursnumberno

Hours required, for subject_hours rules. Counted from quantity evidence in hours or minutes, plus the elapsed time of date_range evidence.

threshold_countintegerno

Completed records required, for subject_record_count rules.

evidence_typestringno

Evidence type that must be present, for evidence_document rules. A pass_fail rule is met only by a row recording a pass.

one of "score" | "date_range" | "quantity" | "url" | "file" | "pass_fail" | "note"

quiz_idstring (uuid)no

Quiz that must be passed, for quiz_pass rules. A quiz of the type's own organization.

external_course_idstring (uuid)no

Catalogue id of the external LMS course that must be passed, for external_course_pass rules. A course of the type's own organization. Passing is decided by the course: its passing_score when set, the imported passed flag otherwise.

scorm_course_idstring (uuid)no

Hosted SCORM course that must be completed, for scorm_course_complete rules. A course of the type's own organization. Completion is what the course's completion records count: an attempt the module reported complete without an explicit failed verdict.

job_aid_idstring (uuid)no

Job aid that must be viewed, for job_aid_viewed rules. An aid of the type's own organization. Viewing is an open of the aid's page (POST /job-aids/{job_aid_id}/views, which the page does on every load), inside the current recertification window; opens of its individual files do not count.

subject_matter_idstring (uuid) | nullno

Narrows a threshold rule to one of the type's subject tags; send null to count every tag again.

Responses

StatusDescriptionBody
200The updated rule.CertificationRule
400The request body failed validation, or does not fit the rule's kind.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller can read this rule but does not hold certifications:write.ErrorResponse
404No visible rule has that id.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
DELETE/api/certification-rules/{rule_id} Bearer token

Delete a proof rule

Hard-deletes a rule. Every sign-off recorded against it cascades away with it. Requires certifications:write over the type's owner.

Parameters

NameInTypeRequiredDescription
rule_idpathstring (uuid)yesUUID id of the proof rule.

Responses

StatusDescriptionBody
200The deleted rule.CertificationRule
401The access token is missing or invalid.ErrorResponse
403The caller can read this rule but does not hold certifications:write.ErrorResponse
404No visible rule has that id.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
GET/api/organizations/{org_id}/departments/{dept_id}/roles/{role_id}/required-certifications Bearer token

List a role's required certifications

Lists the certification types required of everyone holding one department role, with each link's recertification scheme. Requires certifications:read; links whose type is outside the caller's scope are absent.

Parameters

NameInTypeRequiredDescription
org_idpathstringyesOrganization UUID id or slug.
dept_idpathstringyesDepartment UUID id or slug, resolved within the organization.
role_idpathstringyesRole UUID id or slug, resolved within the department.

Responses

StatusDescriptionBody
200The role's requirement links.RoleRequiredCertificationList
401The access token is missing or invalid.ErrorResponse
404The organization, department or role does not exist.ErrorResponse
500The database could not be read.ErrorResponse
POST/api/organizations/{org_id}/departments/{dept_id}/roles/{role_id}/required-certifications Bearer token

Require a certification of a role

Links a certification type to a department role, with a recertification scheme and an optional role-level initial due date every holder inherits. Requires certifications:write over the type's owner. The type must belong to the role's organization.

Parameters

NameInTypeRequiredDescription
org_idpathstringyesOrganization UUID id or slug.
dept_idpathstringyesDepartment UUID id or slug, resolved within the organization.
role_idpathstringyesRole UUID id or slug, resolved within the department.

Request body

application/jsonrequiredCreateRoleRequiredCertificationRequest
FieldTypeRequiredDescription
certification_type_idstring (uuid)yes

A certification type of the same organization as the role's department.

recert_schemestringyes

none: certify once, never again. anniversary: due recert_interval_months after each award. fixed_calendar: due on recert_anchor_month/recert_anchor_day each year.

one of "none" | "anniversary" | "fixed_calendar"

recert_interval_monthsintegerno

Months between recertifications, for the anniversary scheme.

recert_anchor_monthintegerno

Calendar month (1-12) the certification falls due, for fixed_calendar.

minimum 1 · maximum 12

recert_anchor_dayintegerno

Day of the anchor month (1-31, clamped to the month's length), for fixed_calendar.

minimum 1 · maximum 31

initial_due_atstring (date-time)no

When the *initial* certification falls due for every holder of the role. A member's per-person due date overrides it; omit to set no role-level deadline.

Responses

StatusDescriptionBody
201The created requirement link.RoleRequiredCertification
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold certifications:write over the type's owner.ErrorResponse
404The organization, department, role or certification type does not exist (or the type belongs to another organization).ErrorResponse
409The role already requires that certification type.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse