Update KYB answer
Updates one stored answer. Requires the record-level update permission. Answers 200 through apireply.Ok200, whose body is the shared StdResponse envelope ({status, message}) — NOT the {message: "Answer updated successfully"} object this spec used to document, which the code never produced. The update is a gorm Updates over the decoded struct, which writes every non-zero field it finds. Because the Go type embeds BaseModel, that includes audit columns — see KYBAnswerUpdate.
Authorization
bearerAuth In: header
Path Parameters
Id of the answer row (kyb.answers.id). Read from the chi route context inside the service, not passed as an argument.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Body of PUT /v1/kyb/{kyb_id}. The Go type embeds BaseModel, so the decoder accepts every audit field as well as answer, and the update is issued as gorm Updates over the whole struct — which writes any NON-ZERO field it finds. A caller can therefore set active, metadata, created_by or modified_by on an answer row. Only answer is meaningful to send; the rest are an artefact of the embedded struct, not an intended API. The write surface is wider than the one meaningful field: the Go type embeds BaseModel and the update runs as a GORM Updates over the whole struct, so active, metadata, created_by, modified_by, created_at AND id are all writable from this body. Only answer is meaningful to send.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/v1/kyb/497f6eca-6276-4993-bfeb-53cbbbba6f08" \ -H "Content-Type: application/json" \ -d '{ "answer": {} }'{
"status": 200,
"message": "OK"
}{
"status": 400,
"message": "Invalid input",
"code": "common.invalid_input",
"class": "validation"
}{
"status": 401,
"message": "Failed to check permission",
"code": "common.failed_to_check_permission",
"class": "business"
}{
"status": 403,
"message": "No access to the record",
"code": "common.rbac_no_rec_access",
"class": "business"
}{
"status": 404,
"message": "Record not found",
"code": "common.record_not_found",
"class": "business"
}{
"status": 429,
"message": "Rate limit for 203.0.113.7 to POST:/v1/kyb/navigate exceeded.",
"code": "rate_limits_m.exceeded",
"class": "temporary",
"retryable": true
}{
"status": 500,
"message": "Database error",
"code": "common.database_error",
"class": "business"
}{
"overall_status": "unhealthy",
"message": "Service is shutting down",
"timestamp": "2026-08-27T15:04:05Z"
}Lists stored answers for one actor. The path segment is named customer_id but is matched against the answers table's actor_id column. Record-scoped. A caller without the read-all mask has their permitted answer ids folded into the query, and a caller with NO permitted ids receives 200 with an EMPTY ARRAY — a refusal is indistinguishable from an actor who has answered nothing.
Starts or resumes an actor's questionnaire and returns the step to render. Answers 201 Created on every success, including a plain resume that creates nothing. Two bodies share that status: a running flow returns KYBFlowResponse (flow + question), while a flow whose status is already COMPLETE (upper case) returns KYBFlowCompletedResponse (flow + message, and deliberately NO question — an empty Question value would serialise as a real question and the client would render an empty form). Branch on whether question is present. THERE IS A THIRD RESPONSE SHAPE, and "branch on whether question is present" does not find it. When the resolved step name is SECTION_LIST the handler returns a KYBFlowResponse whose Question is left at its ZERO VALUE — and Question is a value field with no omitempty, so the body carries "question": {"name": "", "q": "", "schema": null, ...}. A client that renders whenever question exists draws an empty form. Branch on flow.CurrentStep == "SECTION_LIST" instead. That response is also rebuilt field by field and copies neither flow_id nor SectionStatus, so a pinned actor's flow_id is absent from this one body — which, by the rule stated on KYBFlow.flow_id, reads as "not pinned" when the actor is in fact pinned.