CorebanqCorebanq Developer Docs
KYBv1KYB Flow

Repin actor flow (admin)

Administratively repins an actor's kyb.flows row to a different snapshot, a different step, or both. Used to recover actors stuck on an inactive snapshot. Admin only: the handler calls requireKYBConfigAdmin, which resolves the caller and then checks Storage.IsAdminAccount. A non-admin gets 403 common.forbidden. At least one of flow_id or current_step must be present; sending neither is 400. Body validation in the handler is shape-level only; that the snapshot and step actually exist is checked inside the storage transaction, AND BOTH OF THOSE ARE 400, NOT 404. A flow_id that names no flows_config row, or one whose flow_name differs from the body's, is kyb_m.invalid_flow_id; a current_step that is not an active item of the effective snapshot is kyb_m.invalid_step. The only 404 on this route is a missing kyb.flows row for the actor. On success the flow_name's config cache is invalidated so the next navigate reads the new layout.

POST
/v1/kyb/admin/flows/repin

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/kyb/admin/flows/repin" \  -H "Content-Type: application/json" \  -d '{    "actor_id": "04f37679-bfbf-4906-b749-01756515cecf",    "flow_name": "string"  }'
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "actor_id": "04f37679-bfbf-4906-b749-01756515cecf",
  "flow_name": "string",
  "flow_id": "0746f03b-16cc-49fb-9833-df3713d407d2",
  "current_step": "string",
  "previous_step": "string"
}
{
  "status": 400,
  "message": "Invalid parameter {param}",
  "code": "kyb_m.invalid_parameter",
  "class": "validation"
}
{
  "status": 401,
  "message": "Unauthorized",
  "code": "common.unauthorized",
  "class": "business"
}
{
  "status": 403,
  "message": "Access denied",
  "code": "common.forbidden",
  "class": "business"
}
{
  "status": 404,
  "message": "Flow not found",
  "code": "kyb_m.flow_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": "Internal server error",
  "code": "common.server_error",
  "class": "business"
}

{
  "overall_status": "unhealthy",
  "message": "Service is shutting down",
  "timestamp": "2026-08-27T15:04:05Z"
}

POSTNavigate KYB flow

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.

POSTSubmit answer

Stores an answer and advances the flow. Answers 200, with the same two-body split as navigate: KYBFlowResponse while the flow runs, KYBFlowCompletedResponse once its status is COMPLETE (upper case). Only actor_id and flow_name are validated. question_name is intentionally unchecked — it is empty when the flow has already ended. The body is read with a plain json.NewDecoder, so no struct validation runs and unknown members are ignored.