Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

KYC API Frontend Guide

This public course helps frontend teams build regulated onboarding, due diligence, case review, customer refresh, and compliance operations products on top of the KYC API.

The course is written for implementation. It teaches the browser-safe API contract, the screens to build, the product states to handle, and the security boundaries a frontend team must preserve.

The structure is deliberately incremental: each topic has one job, one visible outcome, and a checkpoint before the next topic. You can follow the course from the beginning, or you can enter through the page that matches the screen you are building today.

Who This Is For

  • Frontend engineers integrating a KYC or due diligence API.
  • Product engineers building onboarding or review workflows.
  • Technical leads coaching a team through regulated API integration.
  • LLM coding agents that need a precise implementation contract.

What You Will Learn

  • How the frontend-facing API capabilities fit together.
  • How to configure the API boundary without leaking secrets.
  • How to build a typed API client.
  • How to add diagnostics before product screens.
  • How to treat API errors as product states.
  • How to render quick screening evidence.
  • How to create and update durable case workspaces.
  • How to generate report snapshots.
  • How to poll workflow events.
  • How to keep recommendations separate from human decisions.
  • How to adapt the same integration pattern to banks, fintechs, insurers, marketplaces, lenders, and other regulated products.

How The Course Is Organized

  • Course Map gives the recommended learning path.
  • Big Picture explains the system model.
  • Workflow pages show complete product paths.
  • Foundation pages define reusable contracts.
  • Task pages build one API-backed feature at a time.
  • Quality pages verify accessibility, audit readiness, tests, and launch safety.

Public-Safe Scope

This guide intentionally avoids internal implementation details. It focuses on the public frontend contract: endpoints, request shapes, response states, security rules, and user experience patterns.

For autonomous implementation, see the LLM Coder Agent Contract.

Course Map

This course teaches frontend teams how to build regulated product workflows on top of the KYC API.

The course is now organized as topic pages. You can read it from start to finish, but you do not have to. Each page gives enough context to work on that topic directly, then links to the pages that naturally come before or after it.

What You Will Be Able To Build

After working through the course, you should be able to:

  1. Configure a browser application without leaking secrets.
  2. Build a typed TypeScript client for protected KYC API calls.
  3. Diagnose connectivity, readiness, and authentication problems.
  4. Render API errors as useful product states.
  5. Build quick screening as evidence, not a final decision.
  6. Create durable case workspaces.
  7. Save one case section at a time.
  8. Generate and read report snapshots.
  9. Display workflow progress without treating events as the compliance archive.
  10. Keep generated recommendations separate from human review decisions.
  11. Adapt the same integration pattern to banks, fintechs, insurers, lenders, marketplaces, and other regulated products.

Start Here

Use these pages first:

Choose A Workflow

If you are building a concrete product surface, start with one workflow:

GoalStart with
Show API status and user accessRead-Only Dashboard
Collect user or applicant detailsCase Intake Form
Support analyst or reviewer workReviewer Workspace
Prepare a regulated frontend for releaseLaunch-Ready Frontend

Each workflow links to smaller task pages instead of repeating the same implementation guidance.

Topic Types

The course uses predictable topic types:

Topic typePurpose
Big pictureExplains the full system and how the pages fit together.
WorkflowShows an end-to-end product path and links to task pages.
FoundationEstablishes a reusable boundary, type, client, or state model.
TaskBuilds one API-backed feature.
QualityVerifies accessibility, audit readiness, tests, and launch safety.

How To Use A Topic Page

Every implementation page follows the same rhythm:

  1. Use this when tells you whether the page matches your problem.
  2. What you will build defines the visible outcome.
  3. What must already be true lists the prerequisites.
  4. API contract names the endpoint or data shape.
  5. UI states turns API behavior into product behavior.
  6. Implementation steps gives the build sequence.
  7. Checkpoint gives a clear stopping point.
  8. Common mistakes prevents predictable integration bugs.
  9. Related pages points to adjacent work.

This keeps each page useful when reached from search, a teammate’s link, or an LLM coding agent.

Stable Implementation Order

When in doubt, build in this order:

configuration -> API client -> diagnostics -> errors -> screening -> cases -> reports -> review

Do not build every screen at once. Finish one visible layer, run its checkpoint, then move to the next layer.

Final Teaching Pattern

Use this sequence when coaching a frontend team:

  1. Prove the API is reachable.
  2. Prove authentication works.
  3. Prove structured errors are useful.
  4. Render evidence without making a decision.
  5. Persist the case.
  6. Save one section at a time.
  7. Generate the right report view.
  8. Show progress while work is active.
  9. Require an accountable human decision.
  10. Verify the customer-facing view hides restricted data.

That sequence turns an API integration into a reliable product workflow.

Big Picture

Use This When

Use this page when you need the overall map before choosing an implementation topic.

What You Will Build

You will build a frontend that turns the KYC API into regulated product workflows: diagnostics, screening, cases, section updates, reports, workflow progress, and human review.

What Must Already Be True

  • You are building a browser or web application.
  • The API owner can provide public frontend configuration.
  • The target product has a sign-in flow or can add one.

Mental Model

Think of the KYC API as six frontend-facing capabilities.

CapabilityFrontend responsibilityAPI responsibility
AccessSign in the user and send a short-lived bearer token.Validate the token and authorize protected requests.
DiagnosticsShow whether the API is reachable and ready.Expose health and readiness endpoints.
Screening evidenceCollect search input and render evidence clearly.Return screening status, evidence status, limitations, and next steps.
Case workspaceLet operators create and update a review file.Persist durable case records and section updates.
Report snapshotsRequest the correct report view and display it safely.Generate immutable report artifacts with snapshot metadata.
Human reviewRequire reviewer action and rationale.Record accountable review decisions.

The frontend orchestrates the experience. The API owns the regulated workflow contract.

Course Path

The stable learning path is:

  1. Draw the Integration Boundary.
  2. Configure the Environment.
  3. Build the API Client.
  4. Add Diagnostics.
  5. Convert failures into Error States.
  6. Build Quick Screening.
  7. Create Durable Cases.
  8. Save Case Sections.
  9. Generate Report Snapshots.
  10. Display Workflow Events.
  11. Submit Human Review Decisions.
  12. Run the Launch Checklist.

Checkpoint

You are ready to start implementation when you can explain:

  • Which values are public browser configuration.
  • Which credentials must never reach the browser.
  • Which page owns diagnostics, errors, screening, cases, reports, and review.
  • Which workflow you are building first.

Common Mistakes

  • Building product screens before diagnostics.
  • Treating quick screening as final approval.
  • Mixing generated recommendations with human decisions.
  • Showing compliance-only report data on customer-facing routes.
  • Letting every screen invent its own API request logic.

Read-Only Dashboard

Use This When

Use this workflow when the first product goal is to show API status, user access, latest evidence, or report information without editing a case.

What You Will Build

You will build a dashboard that proves the API is reachable, the user can authenticate, and read-only KYC information can be displayed safely.

What Must Already Be True

API Contract

Typical endpoints:

GET /healthz
GET /readyz
GET /api/v1/kyc/search
GET /api/v1/kyc-cases/{case_id}
GET /api/v1/kyc-cases/{case_id}/reports/latest?view={view}
GET /api/v1/workflow/events?after_id={after_id}&limit={limit}

Choose only the endpoints needed for the dashboard.

UI States

AreaRequired states
DiagnosticsReachable, not reachable, ready, degraded.
AuthSigned out, signed in, unauthorized.
EvidenceEmpty, loading, success, partial evidence, error.
ReportNo report, loading, snapshot available, restricted view.
TimelineNo events, polling, warning, error.

Implementation Steps

  1. Add Diagnostics.
  2. Add Error States.
  3. Add Quick Screening if dashboard users need lightweight evidence lookup.
  4. Add Report Snapshots when the dashboard displays generated summaries.
  5. Add Workflow Events when active work is visible.

Checkpoint

  • A user can tell whether the API, readiness, and auth are working.
  • Read-only views do not expose restricted compliance fields to customer-facing audiences.
  • Support details preserve API request metadata when failures occur.

Common Mistakes

  • Starting with reports before diagnostics works.
  • Rendering compliance report data in a general support dashboard.
  • Polling workflow events after the dashboard is no longer visible.
  • Treating read-only UI as permission enforcement.

Case Intake Form

Use This When

Use this workflow when the frontend collects applicant, customer, borrower, seller, or policyholder details and creates a durable case.

What You Will Build

You will build intake that validates input, optionally runs quick screening, creates a durable case, and routes the user to a case workspace.

What Must Already Be True

  • The app has browser-safe auth.
  • The shared API Client exists.
  • Required public configuration is available.

API Contract

Typical endpoints:

GET /api/v1/kyc/search
POST /api/v1/kyc-cases
PATCH /api/v1/kyc-cases/{case_id}/sections/{section_name}

Use quick screening before case creation only when it helps the product flow.

UI States

AreaRequired states
FormEmpty, invalid, ready, submitting.
ScreeningNot run, running, evidence available, partial evidence.
Case creationSaving, created, duplicate external ID, validation error.
NavigationStay on form for fixable errors, route to workspace on success.

Implementation Steps

  1. Add Error States.
  2. Add Quick Screening when intake needs a first evidence pass.
  3. Add Create Durable Cases.
  4. Add Case Sections if intake saves additional sections after the case exists.
  5. Run Accessible Product States for form labels, validation, keyboard behavior, and focus handling.

Checkpoint

  • Missing or invalid input is caught before submit when possible.
  • API validation errors map back to the form.
  • Duplicate external case IDs show a recovery path.
  • Successful creation moves the user to the case workspace.

Common Mistakes

  • Saving a durable case before the user has entered required identity context.
  • Treating a quick screening result as the final intake decision.
  • Losing form state when the API returns a validation error.
  • Requiring an external case ID when the API can generate one safely.

Reviewer Workspace

Use This When

Use this workflow when analysts or authorized reviewers need to inspect a case, save sections, read reports, track progress, and submit decisions.

What You Will Build

You will build the primary regulated review surface: case detail, section editing, evidence panels, reports, workflow timeline, and decision submission.

What Must Already Be True

  • A durable case can be created or loaded.
  • The user is authenticated and authorized for reviewer work.
  • Customer-facing and reviewer-facing routes are separated.

API Contract

Typical endpoints:

GET /api/v1/kyc-cases/{case_id}
PATCH /api/v1/kyc-cases/{case_id}/sections/{section_name}
POST /api/v1/kyc-cases/{case_id}/reports/end-user-v1
GET /api/v1/kyc-cases/{case_id}/reports/latest?view={view}
GET /api/v1/workflow/events?after_id={after_id}&limit={limit}
POST /api/v1/kyc-cases/{case_id}/review-decisions

UI States

AreaRequired states
Case detailLoading, found, missing, unauthorized.
SectionsClean, dirty, saving, saved, validation error.
EvidenceAvailable, partial, unavailable, restricted.
ReportsNo snapshot, generating, cache hit, cache miss, restricted.
EventsPolling, idle, warning, error.
DecisionNot ready, rationale required, submitting, submitted.

Implementation Steps

  1. Load the case and render server-owned fields as read-only.
  2. Add Case Sections.
  3. Add evidence panels from Quick Screening or saved screening sections.
  4. Add Report Snapshots.
  5. Add Workflow Events.
  6. Add Human Review Decisions.
  7. Run Audit-Ready UI before launch.

Checkpoint

  • Reviewers can understand evidence, reports, workflow progress, and required decisions without mixing them together.
  • Recommendations and human decisions are visually separate.
  • Restricted sections do not appear in customer-facing routes.

Common Mistakes

  • Putting every case field into one large form.
  • Hiding report view type or snapshot metadata from reviewers.
  • Letting the decision button submit without rationale.
  • Showing generated recommendations as if they were decisions.

Launch-Ready Frontend

Use This When

Use this workflow when a prototype is moving toward production use in a regulated product.

What You Will Build

You will turn a working integration into a launch-ready frontend by checking configuration, security boundaries, accessible states, audit readiness, tests, and release assumptions.

What Must Already Be True

  • The main product workflow is implemented.
  • The app can call the API in at least one non-production environment.
  • Auth, CORS or origin allowlist, and protected endpoint access can be verified.

API Contract

The launch gate should cover every endpoint your product calls, especially:

GET /healthz
GET /readyz
GET /api/v1/kyc/search
POST /api/v1/kyc-cases
PATCH /api/v1/kyc-cases/{case_id}/sections/{section_name}
POST /api/v1/kyc-cases/{case_id}/reports/end-user-v1
GET /api/v1/kyc-cases/{case_id}/reports/latest?view={view}
POST /api/v1/kyc-cases/{case_id}/review-decisions

UI States

Launch-ready means every critical flow has:

  • Empty state.
  • Loading state.
  • Success state.
  • Validation error state.
  • Auth or permission error state.
  • Conflict state where relevant.
  • Retry or support handoff state when relevant.

Implementation Steps

  1. Run Accessible Product States.
  2. Run Audit-Ready UI.
  3. Run Testing Checklist.
  4. Run Launch Checklist.
  5. Verify production configuration outside the source tree.
  6. Confirm support handoff includes request metadata without exposing secrets.

Checkpoint

  • The app has a verified path for diagnostics, auth, validation errors, conflicts, screening, case creation, section save, report generation, workflow progress, and review decision submission.

Common Mistakes

  • Calling a prototype launch-ready because the happy path works once.
  • Skipping customer-safe report verification.
  • Leaving private values in public environment examples.
  • Not testing duplicate external IDs or expired-token behavior.

Integration Boundary

Use This When

Use this page before writing API calls, auth wiring, or UI screens.

What You Will Build

You will define the browser-safe boundary for a frontend integration with the KYC API.

What Must Already Be True

  • You know which frontend application will call the API.
  • You can get public configuration from the API owner.
  • You have a user sign-in strategy or a plan to add one.

API Contract

The frontend can rely on public API endpoints and response contracts. It should not depend on internal hosting, storage, scoring, routing, or operator tooling.

The browser may contain:

  • Public API base URL.
  • Public auth issuer URL.
  • Public frontend auth client ID.
  • Redirect URI.
  • Post-logout redirect URI.
  • Required API audience or scope when provided.

The browser must never contain:

  • Service-account keys.
  • Private keys.
  • Backend secrets.
  • Database URLs.
  • Token-introspection credentials.
  • Long-lived bearer credentials.
  • Provider credentials.

UI States

The boundary should show up in the product:

StateProduct behavior
Missing public configStop startup or show setup diagnostics.
Missing user tokenShow sign-in state.
Unauthorized requestRecover auth or send the user to sign in.
Support handoffPreserve API request_id and trace_id when present.

Implementation Steps

  1. List every runtime value the frontend needs.
  2. Classify each value as public browser config or server-side secret.
  3. Add startup validation for required public values.
  4. Route all protected calls through one API client.
  5. Preserve structured API error metadata for support.

Checkpoint

  • Environment files do not contain private credentials.
  • Protected calls use the current user’s bearer token.
  • UI copy does not promise that screening evidence equals final approval.

Common Mistakes

  • Reusing a machine-to-machine credential in browser code.
  • Logging access tokens or regulated payloads.
  • Hardcoding deployment-specific values in reusable source.
  • Exposing operator-only endpoints to ordinary end users.

Environment Configuration

Use This When

Use this page when wiring a frontend app to a real API environment.

What You Will Build

You will define environment-specific public configuration for the browser app and keep private values out of source code.

What Must Already Be True

  • The API owner has assigned an API base URL.
  • The auth owner has configured a public browser client.
  • The frontend origin is allowed by the API owner.

API Contract

Before production wiring, get these values:

KYC API base URL
Auth issuer URL
Public frontend client ID
Redirect URI
Post-logout redirect URI
Required API audience or scope
Allowed frontend origin
Support contact or escalation path

For a Vite application, public variables usually look like:

VITE_KYC_API_BASE_URL=https://api.example.com
VITE_AUTH_ISSUER=https://identity.example.com
VITE_AUTH_CLIENT_ID=public-browser-client-id
VITE_AUTH_REDIRECT_URI=http://localhost:5173/auth/callback
VITE_AUTH_POST_LOGOUT_REDIRECT_URI=http://localhost:5173/
VITE_AUTH_AUDIENCE_SCOPE=api-audience-scope

Use the target application’s naming convention when it differs from Vite.

UI States

Configuration should support these states:

StateProduct behavior
Config validEnable diagnostics and sign-in.
API base URL missingShow setup error before protected screens load.
Auth issuer missingDisable sign-in and show setup guidance.
Origin not allowedDiagnostics should point to CORS or origin allowlist.

Implementation Steps

  1. Add a small config module at the frontend app boundary.
  2. Read only public environment variables in browser code.
  3. Validate required values at startup.
  4. Fail clearly when a required value is missing.
  5. Link config errors to the diagnostics screen.

Checkpoint

  • Local development can load public config.
  • Production config can be supplied without changing source code.
  • No private key, service credential, database URL, or long-lived token appears in the frontend bundle.

Common Mistakes

  • Treating public client IDs as secrets.
  • Treating service credentials as public config.
  • Committing .env files.
  • Letting a missing config value produce a generic blank screen.

API Client

Use This When

Use this page when adding the first real API calls to a frontend application.

What You Will Build

You will build one small TypeScript API client that attaches user tokens, parses JSON, and converts non-2xx responses into structured errors.

What Must Already Be True

  • Public API configuration is available.
  • The application can provide the current user’s access token or null.
  • The frontend has a place for shared API modules.

API Contract

Protected API calls send:

Authorization: Bearer <access_token>

The token must come from the current user’s browser sign-in flow, normally authorization code with PKCE or an equivalent repository-provided pattern.

Implementation Steps

Start with one client that is independent from UI components:

export type KycApiClientOptions = {
  baseUrl: string;
  getAccessToken: () => Promise<string | null>;
};

export type KycApiErrorBody = {
  code: string;
  message: string;
  developer_message?: string;
  category?: string;
  http_status?: number;
  request_id?: string;
  trace_id?: string;
  retryable?: boolean;
  docs_url?: string;
  details?: Record<string, unknown>;
};

export class KycApiError extends Error {
  readonly developerMessage?: string;
  readonly category?: string;
  readonly requestId?: string;
  readonly traceId?: string;
  readonly retryable: boolean;
  readonly details?: Record<string, unknown>;

  constructor(
    message: string,
    readonly status: number,
    readonly code?: string,
    readonly responseBody?: unknown
  ) {
    super(message);

    const body = (responseBody as { error?: KycApiErrorBody } | null)?.error;
    this.developerMessage = body?.developer_message;
    this.category = body?.category;
    this.requestId = body?.request_id;
    this.traceId = body?.trace_id;
    this.retryable = body?.retryable ?? false;
    this.details = body?.details;
  }

  get field(): string | undefined {
    return typeof this.details?.field === "string" ? this.details.field : undefined;
  }
}

Wrap fetch once:

export class KycApiClient {
  constructor(private readonly options: KycApiClientOptions) {}

  get<T>(path: string): Promise<T> {
    return this.request<T>("GET", path);
  }

  post<T>(path: string, body: unknown): Promise<T> {
    return this.request<T>("POST", path, body);
  }

  patch<T>(path: string, body: unknown): Promise<T> {
    return this.request<T>("PATCH", path, body);
  }

  private async request<T>(
    method: "GET" | "POST" | "PATCH",
    path: string,
    body?: unknown
  ): Promise<T> {
    const token = await this.options.getAccessToken();
    const response = await fetch(new URL(path, this.options.baseUrl), {
      method,
      headers: {
        Accept: "application/json",
        ...(body ? { "Content-Type": "application/json" } : {}),
        ...(token ? { Authorization: `Bearer ${token}` } : {})
      },
      body: body ? JSON.stringify(body) : undefined
    });

    const text = await response.text();
    const parsed = text ? JSON.parse(text) : null;

    if (!response.ok) {
      throw new KycApiError(
        parsed?.error?.message ?? `KYC API returned HTTP ${response.status}`,
        response.status,
        parsed?.error?.code,
        parsed
      );
    }

    return parsed as T;
  }
}

Create the instance at the app boundary:

export const kycApi = new KycApiClient({
  baseUrl: import.meta.env.VITE_KYC_API_BASE_URL,
  getAccessToken
});

UI States

The API client should make these states easy to render:

StateSource
LoadingThe request promise is pending.
SuccessThe typed response is returned.
Validation errorKycApiError.status === 400.
Auth errorKycApiError.status === 401.
ConflictKycApiError.status === 409.
Retry laterKycApiError.retryable === true.

Checkpoint

  • All API calls use the same client.
  • Protected requests attach Authorization: Bearer <access_token>.
  • Non-2xx responses throw KycApiError.
  • request_id is available for support handoff.

Common Mistakes

  • Creating one fetch wrapper per screen.
  • Dropping request_id from errors.
  • Assuming every response body is valid JSON without reading the response text.
  • Retrying compliance-changing mutations blindly.

Diagnostics

Use This When

Use this page before building product screens or when an integration fails in a new environment.

What You Will Build

You will build a diagnostics screen that separates API reachability, readiness, and authentication problems.

What Must Already Be True

  • Public API base URL is configured.
  • The shared API Client exists.
  • The application can tell whether a user is signed in.

API Contract

Public operational endpoints:

GET /healthz
GET /readyz

Suggested response types:

export type HealthResponse = {
  status: string;
  release?: string;
  runtime?: {
    git_sha?: string;
    image_ref?: string;
    fly_app_name?: string;
    fly_process_group?: string;
    fly_region?: string;
  };
};

export type ReadinessResponse = {
  status: string;
  release?: string;
  runtime?: HealthResponse["runtime"];
  checks?: Array<{
    name: string;
    ok: boolean;
    detail?: string;
  }>;
};

Load public diagnostics:

export async function loadApiDiagnostics(client: KycApiClient) {
  const [health, readiness] = await Promise.all([
    client.get<HealthResponse>("/healthz"),
    client.get<ReadinessResponse>("/readyz")
  ]);

  return { health, readiness };
}

After sign-in, verify one protected endpoint that matches the product you are building.

UI States

StateMeaningUser action
ReachableBrowser can call public API endpoints.Continue setup.
Not reachableNetwork, base URL, CORS, or DNS may be wrong.Check API base URL and frontend origin.
ReadyAPI reports it can handle work.Continue product flow.
DegradedAPI is reachable but not fully ready.Show diagnostics and retry later.
AuthenticatedUser token is present and accepted.Enable protected flows.
UnauthorizedToken is missing, expired, or invalid.Sign in again.

Developer diagnostics should show the API release, deployment/runtime metadata, and any failed readiness check names. Do not show /metrics in customer-facing UI; it is an operator/debug endpoint.

Implementation Steps

  1. Add a diagnostics route or admin-only panel.
  2. Call /healthz and /readyz without requiring sign-in.
  3. Show configuration, reachability, readiness, and auth as separate rows.
  4. After sign-in, call one protected endpoint and show whether the token works.
  5. Include request_id when a protected diagnostic request fails.

Checkpoint

  • A developer can diagnose base URL, readiness, and auth problems without opening browser devtools.
  • A developer can compare the frontend environment against the backend release currently serving the API.
  • The diagnostics page does not expose private credentials or regulated data.

Common Mistakes

  • Hiding diagnostics behind the same auth problem being diagnosed.
  • Calling only protected endpoints and missing CORS or readiness failures.
  • Showing raw tokens in debug output.
  • Treating degraded readiness as a user input error.

Error States

Use This When

Use this page when turning API failures into clear UI behavior.

What You Will Build

You will map structured API errors to validation messages, auth recovery, missing-resource screens, conflict resolution, retry states, and support handoff.

What Must Already Be True

  • The shared API Client throws KycApiError.
  • The UI has a place to render field, form, page, and support messages.

API Contract

Preserve these fields when the API returns them:

status
code
message
developer_message
category
request_id
trace_id
retryable
details

Useful guards:

export function isValidationError(error: unknown): error is KycApiError {
  return error instanceof KycApiError && error.status === 400;
}

export function isUnauthorized(error: unknown): error is KycApiError {
  return error instanceof KycApiError && error.status === 401;
}

export function isConflict(error: unknown): error is KycApiError {
  return error instanceof KycApiError && error.status === 409;
}

export function isRetryableServiceError(error: unknown): error is KycApiError {
  return error instanceof KycApiError && error.retryable;
}

UI States

StatusUI behavior
400Show field or form validation. Use details.field when present.
401Refresh login or redirect to sign in.
404Show missing resource state and route back to a safe page.
409Offer to load the existing case or create a new external identifier.
429Show overloaded/retry-later state and use Retry-After or exponential backoff.
503Show degraded service, retry later, and include request_id in support details.

Implementation Steps

  1. Create one error-to-UI mapping module.
  2. Render field errors near the relevant form inputs.
  3. Render auth failures as sign-in recovery, not data-entry mistakes.
  4. Render conflicts as recoverable choices.
  5. Render retryable failures with retry and support handoff.

Checkpoint

  • Field errors appear near the relevant input.
  • Authentication errors do not look like validation errors.
  • Conflict errors give the operator a recoverable path.
  • Support details include request_id when the API provides it.
  • Retryable overload errors are handled without repeatedly hammering the API.

Common Mistakes

  • Collapsing all failures into “Something went wrong.”
  • Hiding developer context that support needs.
  • Showing developer-only messages to customers.
  • Retrying non-idempotent actions without user intent.

Data Shapes And Vocabulary

Use This When

Use this page when naming types, UI labels, route names, or documentation in a frontend implementation.

What You Will Build

You will keep product language consistent across code, screens, support handoff, and tests.

What Must Already Be True

  • You have read the Big Picture.
  • You know which workflow the frontend will support first.

Vocabulary

TermMeaning
API clientThe frontend module that wraps fetch, attaches tokens, and parses errors.
DiagnosticsHealth, readiness, and authenticated access checks.
Quick screeningA lightweight evidence search. It is not a final approval.
CaseA durable review file for one customer, seller, borrower, policyholder, or subject.
SectionOne named part of a case file, saved independently.
Report snapshotA generated report artifact with ID, hash, view, timestamp, and payload.
Workflow eventA progress event for active work. It is not the permanent compliance archive.
RecommendationGenerated or assisted guidance shown to a reviewer.
DecisionThe accountable human action submitted by an authorized reviewer.

The API uses technical parameter names such as include_web_search. Your UI can label the same control “evidence search” if that is clearer for users.

UI States

Vocabulary should make state obvious:

StatePreferred language
Evidence only“Screening evidence” or “evidence search result”.
Human action required“Reviewer decision required”.
Customer-safe report“Customer summary” or product-specific equivalent.
Restricted data“Internal review only” or role-specific label.

Implementation Steps

  1. Create shared TypeScript types for API concepts.
  2. Use product labels in the UI while preserving API field names in client code.
  3. Keep recommendations, decisions, reports, and events as separate types.
  4. Add test fixtures using the same vocabulary as the UI.

Checkpoint

  • A teammate can read a screen, test, or type name and know whether it is evidence, a recommendation, a decision, an event, or a report snapshot.

Common Mistakes

  • Calling a quick screening result “approved”.
  • Treating workflow events as the audit archive.
  • Mixing customer-safe and compliance report views in one component.
  • Using different names for the same concept in code and UI.

Quick Screening

Use This When

Use this page when an operator needs a lightweight evidence check before opening or updating a durable case.

What You Will Build

You will build a search form and results view that presents screening evidence, limitations, and next steps without presenting the result as final approval.

What Must Already Be True

API Contract

Endpoint:

GET /api/v1/kyc/search

Request query:

name={name}
date_of_birth={date_of_birth}
nationality={nationality}
include_web_search={true_or_false}
limit={limit}

Only name is required.

TypeScript shape:

export type KycSearchParams = {
  name: string;
  dateOfBirth?: string;
  nationality?: string;
  includeEvidenceSearch?: boolean;
  limit?: number;
};

export async function searchKyc(client: KycApiClient, params: KycSearchParams) {
  const query = new URLSearchParams({
    name: params.name,
    include_web_search: String(params.includeEvidenceSearch ?? true),
    limit: String(params.limit ?? 5)
  });

  if (params.dateOfBirth) {
    query.set("date_of_birth", params.dateOfBirth);
  }

  if (params.nationality) {
    query.set("nationality", params.nationality);
  }

  return client.get<KycSearchResponse>(`/api/v1/kyc/search?${query}`);
}

Render these response areas:

  • Subject and generated timestamp.
  • Overall status and risk level.
  • Local sanctions screening status and source versions.
  • Evidence-search status, result counts, and query-level failures.
  • Recommended next steps.
  • Limitations.

UI States

StateProduct behavior
EmptyShow a short form with required name.
LoadingDisable submit and show that screening is running.
SuccessRender evidence, limitations, and next steps.
Partial evidenceShow degraded query/source information clearly.
Validation errorPut the message near the relevant input.
Auth errorAsk the user to sign in again.

Implementation Steps

  1. Build a small form with name, optional date of birth, optional nationality, evidence-search toggle, and result limit.
  2. Validate name before calling the API.
  3. Call searchKyc through the shared client.
  4. Render screening status and evidence-search status separately.
  5. Put limitations close to the summary.
  6. Offer a next action such as creating or opening a durable case.

Checkpoint

  • A user can understand what was checked, what was degraded, and what should happen next.
  • No quick-screening result is labeled as final approval.

Common Mistakes

  • Converting risk level directly into an approval button.
  • Hiding partial evidence failures.
  • Dropping limitations below the fold where reviewers miss them.
  • Logging raw search payloads to analytics.

Create Durable Cases

Use This When

Use this page when a workflow needs persistence, reviewer activity, report snapshots, future refreshes, or customer support handoff.

What You Will Build

You will build case creation that routes the user into a durable case workspace.

What Must Already Be True

  • API Client is implemented.
  • Form validation and Error States are ready.
  • The product has a route for a case workspace or case detail page.

API Contract

Endpoint:

POST /api/v1/kyc-cases

Minimal frontend input shape:

export type KycCaseCreateInput = {
  kyc_case_id?: string | null;
  user_internal_id: string;
  agency_name: string;
  regulated_provider_name: string;
  programme_name: string;
  country_of_onboarding: string;
  relationship_type:
    | "NEW_ONBOARDING"
    | "KYC_REFRESH"
    | "LIMIT_INCREASE"
    | "REMEDIATION"
    | "REACTIVATION";
  user_type:
    | "INDIVIDUAL"
    | "SOLE_TRADER"
    | "LEGAL_REPRESENTATIVE"
    | "BENEFICIAL_OWNER";
  current_status:
    | "DRAFT"
    | "DOCUMENTS_SUBMITTED"
    | "EXTRACTION_IN_PROGRESS"
    | "EXTRACTION_FAILED"
    | "PENDING"
    | "PENDING_REVIEW"
    | "WAITING_FOR_CUSTOMER"
    | "ESCALATED"
    | "SUSPENDED";
  case_priority: "LOW" | "NORMAL" | "HIGH" | "URGENT";
  assigned_team: string;
  assigned_analyst_name?: string | null;
  assigned_analyst_email?: string | null;
  legal_first_name: string;
  legal_last_name: string;
};

export async function createKycCase(
  client: KycApiClient,
  input: KycCaseCreateInput
) {
  return client.post<{ principal: string; case: KycCaseRecord }>(
    "/api/v1/kyc-cases",
    input
  );
}

UI States

StateProduct behavior
DraftLet the user enter required case fields.
SavingDisable duplicate submit and show progress.
CreatedRoute to the case workspace.
ConflictOffer to load the existing case or use a new external ID.
Validation errorShow field-level guidance.
Server-owned fieldsDisplay as read-only after creation.

Implementation Steps

  1. Let the API generate kyc_case_id unless your product owns a stable external case ID.
  2. Keep final statuses out of the creation form.
  3. Validate required fields before submit.
  4. Submit through createKycCase.
  5. On success, navigate to the case workspace.
  6. On duplicate external ID, show a recoverable conflict state.

Checkpoint

  • Creating a case routes the user into a case workspace.
  • Server-owned fields are displayed but not edited.
  • A duplicate external ID shows a conflict path, not a crash.

Common Mistakes

  • Allowing users to create final states directly.
  • Treating server-owned fields as editable inputs.
  • Creating a new case for every quick screening result.
  • Losing the API request_id on conflict or validation failures.

Case Sections

Use This When

Use this page when a case workspace needs to save one part of a case at a time.

What You Will Build

You will build section updates for smaller forms, safer autosave, and clearer review screens.

What Must Already Be True

  • A durable case exists.
  • The UI knows the current case_id.
  • The product can decide which sections are visible to each role.

API Contract

Endpoint:

PATCH /api/v1/kyc-cases/{case_id}/sections/{section_name}

Body:

{
  "payload": {}
}

Common section names:

export type KycSectionName =
  | "service_context"
  | "end_user_identity"
  | "contact_verification"
  | "identity_document_verification"
  | "address_verification"
  | "screening"
  | "risk_assessment"
  | "decision"
  | "user_facing_summary"
  | "restricted_compliance_notes";

export async function patchKycSection(
  client: KycApiClient,
  caseId: string,
  sectionName: KycSectionName,
  payload: Record<string, unknown>
) {
  return client.patch<{ principal: string; section: unknown }>(
    `/api/v1/kyc-cases/${encodeURIComponent(caseId)}/sections/${sectionName}`,
    { payload }
  );
}

UI States

SectionTypical screen
end_user_identityIdentity details and subject profile.
contact_verificationEmail, phone, and contact checks.
identity_document_verificationDocument review status.
address_verificationResidence and proof-of-address status.
screeningScreening evidence and match review.
risk_assessmentRisk rationale and review notes.
user_facing_summaryCustomer-safe explanation.
restricted_compliance_notesInternal-only compliance notes.

Implementation Steps

  1. Split the case workspace into section components.
  2. Give each section its own draft, saving, saved, and error states.
  3. Save one section at a time.
  4. Refresh the case or section data after a successful save.
  5. Hide restricted sections from customer-facing routes.
  6. Keep backend authorization as the enforcement point.

Checkpoint

  • A section save updates only that part of the case.
  • Restricted sections are hidden from customer-facing routes.
  • Frontend role gating improves usability, while backend authorization remains the enforcement point.

Common Mistakes

  • Submitting the entire case for every small edit.
  • Assuming hidden frontend fields are a security control.
  • Saving restricted notes from customer routes.
  • Losing unsaved form state after a section error.

Report Snapshots

Use This When

Use this page when the frontend needs generated reports for customers, partners, providers, or internal reviewers.

What You Will Build

You will generate and read report snapshots with the correct view for the audience.

What Must Already Be True

  • A durable case exists.
  • The user is authorized for the requested report view.
  • Customer-facing and internal routes are separated.

API Contract

Generate:

POST /api/v1/kyc-cases/{case_id}/reports/end-user-v1

Read latest:

GET /api/v1/kyc-cases/{case_id}/reports/latest?view={view}

Allowed views:

user_safe
provider_export
compliance

TypeScript helpers:

export type ReportView = "compliance" | "provider_export" | "user_safe";

export async function generateEndUserReport(
  client: KycApiClient,
  caseId: string,
  view: ReportView
) {
  return client.post<{
    principal: string;
    cache_status: "HIT" | "MISS";
    report_snapshot_id: string;
    generated_at: string;
    input_fingerprint: string;
    snapshot_hash: string;
    view_type: "COMPLIANCE" | "PROVIDER_EXPORT" | "USER_SAFE";
    report: unknown;
  }>(`/api/v1/kyc-cases/${encodeURIComponent(caseId)}/reports/end-user-v1`, {
    view,
    generated_by: "frontend-webapp"
  });
}

export async function loadLatestReport(
  client: KycApiClient,
  caseId: string,
  view: ReportView
) {
  return client.get(
    `/api/v1/kyc-cases/${encodeURIComponent(caseId)}/reports/latest?view=${encodeURIComponent(view)}`
  );
}

UI States

ViewUse it for
user_safeCustomer portals and support experiences.
provider_exportPartner or regulated-provider handoff.
complianceAuthorized internal review workspaces.

Show snapshot metadata in operator-facing screens:

  • cache_status
  • report_snapshot_id
  • snapshot_hash
  • generated_at
  • view_type

Implementation Steps

  1. Choose report view based on route and role.
  2. Generate a report snapshot only when the user requests or workflow requires it.
  3. Display customer-safe reports in customer-facing routes.
  4. Display snapshot metadata in internal operator routes.
  5. Do not render restricted notes in customer-facing routes.

Checkpoint

  • Customer routes use user_safe.
  • Internal review routes can show snapshot metadata.
  • Restricted notes, internal scoring details, and control logic do not appear in customer-facing experiences.

Common Mistakes

  • Using one report view everywhere.
  • Rendering compliance payloads in customer support routes.
  • Hiding snapshot metadata that operators need for support.
  • Regenerating reports on every page load.

Workflow Events

Use This When

Use this page when the frontend needs to show progress while work is active.

What You Will Build

You will poll workflow events, merge them without duplicates, and display warnings and errors clearly.

What Must Already Be True

  • API Client is implemented.
  • The UI has a timeline, activity panel, or progress region.
  • The product knows when active work is visible.

API Contract

Endpoint:

GET /api/v1/workflow/events?after_id={after_id}&limit={limit}

Response shape:

export type WorkflowEvent = {
  id: number;
  timestamp: string;
  level: "info" | "warning" | "error";
  stage: string;
  message: string;
  metadata: Record<string, unknown>;
};

export async function loadWorkflowEvents(client: KycApiClient, afterId: number) {
  return client.get<{
    principal: string;
    events: WorkflowEvent[];
    next_after_id: number;
  }>(`/api/v1/workflow/events?after_id=${afterId}&limit=100`);
}

UI States

StateProduct behavior
No eventsShow a calm empty timeline.
PollingShow progress without blocking unrelated work.
Warning eventHighlight and explain the warning.
Error eventShow failure state and support details when available.
Tab hiddenSlow or pause polling.

Implementation Steps

  1. Start with after_id=0.
  2. Store next_after_id after each response.
  3. Merge events by event.id.
  4. Poll only while active work is visible.
  5. Slow or stop polling when the browser tab is hidden.
  6. Show warning and error events as first-class UI states.

Checkpoint

  • Event polling does not create duplicates.
  • Warning and error events are visible.
  • The UI treats workflow events as progress, not permanent compliance history.

Common Mistakes

  • Polling forever after the user leaves the page.
  • Appending duplicate events.
  • Treating workflow events as the audit archive.
  • Hiding warning and error events in a collapsed debug panel.

Human Review Decisions

Use This When

Use this page when an authorized reviewer must make an accountable decision.

What You Will Build

You will build a review panel that separates evidence, generated recommendations, and the human decision.

What Must Already Be True

  • A durable case exists.
  • Evidence and reports are visible to the reviewer.
  • The reviewer is authorized to submit decisions.

API Contract

Endpoint:

POST /api/v1/kyc-cases/{case_id}/review-decisions

Allowed decision outcomes:

approved
rejected
needs_more_information
escalated

TypeScript helper:

export type ReviewDecisionOutcome =
  | "approved"
  | "rejected"
  | "needs_more_information"
  | "escalated";

export async function submitReviewDecision(
  client: KycApiClient,
  caseId: string,
  body: {
    proposal_id?: string | null;
    decision_outcome: ReviewDecisionOutcome;
    rationale: string;
    decision_payload?: Record<string, unknown>;
    corrections?: Array<Record<string, unknown>>;
  }
) {
  return client.post<{ principal: string; review_decision: unknown }>(
    `/api/v1/kyc-cases/${encodeURIComponent(caseId)}/review-decisions`,
    body
  );
}

UI States

A good review screen has three zones:

ZonePurpose
EvidenceWhat the API returned and what the reviewer should inspect.
RecommendationSuggested outcome, rationale, and limitations.
DecisionThe human action, rationale, and final submission control.

Decision form states:

  • No decision selected.
  • Decision selected but rationale missing.
  • Ready to submit.
  • Submitting.
  • Submitted.
  • Authorization or validation error.

Implementation Steps

  1. Show evidence first.
  2. Show recommendations in a visually separate area.
  3. Require explicit reviewer outcome selection.
  4. Require rationale before submit.
  5. Disable final submit while save or report operations are pending.
  6. Treat needs_more_information as workflow state, not a technical error.
  7. After submitting needs_more_information, update the case UI from the API response and expect resulting_status: "WAITING_FOR_CUSTOMER".

Checkpoint

  • Recommendation and decision are visually separate.
  • The final decision requires a reviewer action.
  • The decision form requires rationale.
  • needs_more_information is treated as workflow state, not a technical error.
  • Frontend state watches the returned case status instead of polling for a separate report-generation job state.

Common Mistakes

  • Combining recommendation and decision into one button.
  • Letting an empty rationale through.
  • Enabling final submit while other case saves are pending.
  • Presenting generated text as the accountable decision.

Accessible Product States

Use This When

Use this page when building or reviewing any screen that calls the KYC API.

What You Will Build

You will make every visible API-backed state understandable, keyboard reachable, and screen-reader friendly.

What Must Already Be True

  • The screen has a clear user goal.
  • The API client and error mapping exist.
  • The product owner knows which roles can use the screen.

UI State Contract

Every critical surface should handle:

StateRequirement
EmptyExplain what the user can do next.
LoadingShow progress without moving layout unexpectedly.
SuccessShow the result and the next safe action.
Validation errorPut the message near the input.
Auth errorShow sign-in recovery.
Permission errorExplain that access is restricted.
ConflictOffer a recoverable choice.
Retryable service failureShow retry and support handoff.

Implementation Steps

  1. Use semantic HTML for forms, tables, lists, and status regions.
  2. Label every input.
  3. Keep keyboard focus visible.
  4. Move focus intentionally after route changes, modal opens, and form errors.
  5. Do not use color alone to communicate risk, status, or severity.
  6. Keep long operations from blocking unrelated navigation.
  7. Preserve API request_id in support details when available.

Checkpoint

  • A user can complete the screen with a keyboard.
  • Errors are readable without relying on color.
  • Loading, empty, success, and error states are all visible in tests or manual review.

Common Mistakes

  • Building only the success state.
  • Showing validation errors in a global toast with no field association.
  • Moving focus unpredictably after save.
  • Hiding retryable failures behind generic copy.

Audit-Ready UI

Use This When

Use this page when the frontend displays regulated evidence, reports, restricted sections, recommendations, or decisions.

What You Will Build

You will make the UI clear about what is evidence, what is generated guidance, what is a human decision, and what is safe for each audience.

What Must Already Be True

  • The product has identified customer-facing and reviewer-facing routes.
  • Report view types are understood.
  • Role-based visibility has been designed for the frontend.

UI Contract

ConceptUI rule
EvidenceShow source, status, limitations, and next steps.
RecommendationPresent as guidance, not final action.
Human decisionRequire explicit reviewer choice and rationale.
Report snapshotPreserve view type, generated timestamp, snapshot ID, and hash where appropriate.
Customer-safe viewHide restricted notes, internal scoring, and compliance-only details.
Restricted sectionHide from customer routes and rely on backend authorization for enforcement.

Implementation Steps

  1. Use separate components for evidence, recommendation, decision, and report snapshot metadata.
  2. Display report view type in reviewer-facing report screens.
  3. Keep customer-safe report rendering separate from compliance report rendering.
  4. Show limitations close to screening summaries.
  5. Require rationale before decision submission.
  6. Exclude personal and regulated data from analytics and client logs.

Checkpoint

  • A reviewer can tell the difference between evidence, recommendation, and decision.
  • Customer routes render only customer-safe report information.
  • Restricted notes do not appear in customer-facing components.

Common Mistakes

  • Reusing one report component for every audience.
  • Putting the final decision button inside the recommendation component.
  • Hiding limitations in a secondary tab.
  • Logging raw regulated payloads during debugging.

Testing Checklist

Use This When

Use this page when adding automated tests or preparing a release branch.

What You Will Build

You will verify the integration with tests that cover the product states a regulated frontend depends on.

What Must Already Be True

  • The target repository has a test runner or component testing strategy.
  • API calls are routed through the shared client.
  • External API calls can be mocked or tested against a controlled environment.

Test Contract

Run the target repository’s actual commands. Prefer:

pnpm typecheck
pnpm lint
pnpm test
pnpm build

If the repository uses npm, yarn, bun, or another tool, use that instead.

Minimum Verification Scenarios

  1. Public health endpoint renders reachable state.
  2. Public readiness endpoint renders ready or degraded state.
  3. Protected request without token redirects or shows sign-in state.
  4. Quick screening form validates missing or short name.
  5. Quick screening success renders evidence and limitations.
  6. API validation error maps to form error.
  7. API 401 maps to auth recovery.
  8. API 409 maps to conflict UI.
  9. Case creation success routes to case workspace.
  10. Section save updates UI without losing unsaved form state.
  11. Report generation shows HIT or MISS cache status.
  12. Workflow polling merges events without duplicates.
  13. Review decision requires rationale.
  14. Customer route does not render compliance-only fields.

Implementation Steps

  1. Add unit tests for API client error parsing.
  2. Add component tests for form validation and error rendering.
  3. Add route or integration tests for diagnostics and auth recovery.
  4. Add workflow tests for case creation, section save, report generation, and review decision.
  5. Add customer-route tests that assert restricted fields are absent.

Checkpoint

  • The happy path and the main failure paths are covered.
  • Tests assert visible product behavior, not only function calls.
  • Test fixtures do not contain real customer data or secrets.

Common Mistakes

  • Mocking the API client so heavily that error parsing is never tested.
  • Testing only the success path.
  • Forgetting customer-safe report assertions.
  • Leaving real regulated payloads in snapshots or fixtures.

Launch Checklist

Use This When

Use this page before moving from prototype to production or before asking a regulated team to rely on the frontend.

What You Will Build

You will complete the final release check for configuration, auth, security boundaries, product states, tests, and support handoff.

What Must Already Be True

  • The main workflow has been implemented.
  • Tests have been added for critical states.
  • A non-production environment can call the API.

Launch Gate

Confirm:

  • The API base URL is environment-specific.
  • The frontend origin is allowed by the API owner.
  • Browser authentication uses a public client flow.
  • No private service credential is shipped to the browser.
  • Protected requests send Authorization: Bearer <access_token>.
  • Errors display useful user states and preserve request_id for support.
  • Developer diagnostics show backend release and failed readiness checks.
  • Request and response types are generated from, or manually reviewed against, the checked OpenAPI contract.
  • Quick screening is not presented as final approval.
  • Customer screens use customer-safe report views.
  • Internal-only sections are hidden from customer-facing routes.
  • Human review actions require explicit rationale.
  • Human follow-up uses needs_more_information; the case workspace should then watch WAITING_FOR_CUSTOMER as the resulting case status.
  • Personal and regulated data are excluded from analytics and client logs.
  • The application has tests for diagnostics, auth failures, validation errors, conflict errors, quick screening, case creation, report generation, workflow polling, and review decision submission.

Implementation Steps

  1. Run local type, lint, test, and build commands.
  2. Verify auth and protected endpoint access in the target environment.
  3. Verify report view permissions.
  4. Review browser bundle and environment files for private values.
  5. Confirm support handoff includes API request metadata.
  6. Document any environment-specific values outside the source tree.

Checkpoint

  • A reviewer can trace each critical product state to a screen and a test.
  • No secret or private credential is present in public source.
  • Any unverified production dependency is documented before launch.

Common Mistakes

  • Treating a passing build as a complete launch gate.
  • Skipping expired-token and duplicate-case tests.
  • Relying on frontend visibility as the only protection for restricted fields.
  • Claiming production readiness before CORS, auth claims, and protected endpoint access have been verified.

LLM Coder Agent Contract

The repository includes a root LLM.txt file for coding agents. It is a plain-text implementation contract that describes:

  • Mission and operating mode.
  • Security rules.
  • Required configuration inputs.
  • API endpoint contracts.
  • TypeScript client shape.
  • Error handling.
  • Feature plan.
  • Testing and verification.
  • Forbidden shortcuts.
  • Done definition.

Use it when asking an autonomous coding agent to implement a frontend application against the KYC API.

Course Pages For Agents

Use these pages to orient an implementation: