Skip to main content
Web ApplicationCompleted

KYC and Document OCR Platform for Fintech Merchant Onboarding

A merchant onboarding platform for a Turkish payment processor that takes new business applications from product selection through identity OCR, tax document extraction, IBAN validation, and operator review, all on a Next.js and Supabase stack.

DeveloperMustafa Kürşad Başer
Started: Aug 2025Completed: Nov 2025
KYC and Document OCR Platform for Fintech Merchant Onboarding

This is the system a Turkish payment processor uses to take a new business from "I want to accept card payments" to "I have an approved merchant account". The product replaces the usual stack of PDF forms, scanned documents emailed to a risk inbox, and operators retyping ID numbers into spreadsheets. Applicants run through a three-phase flow inside one application, documents are read by OCR rather than by hand, and a risk team reviews everything against the form values side by side before approving or rejecting.

The flow has three phases: a product picker (different POS products, each with its own commission, setup time, and required documents), a multi-step form (company, owner, partners, bank details), and a contract step (auto-generated, signed, uploaded back to the system). Application state moves through a draft, submitted, in-review, approved, rejected, and needs-fix lifecycle, with the risk team owning the middle stages.

Identity and document OCR:

  • Turkish ID cards are sent to OpenAI's Vision API (running a cost-efficient default model with an option to upgrade for harder documents) and parsed into a structured payload: TC Kimlik No, name, surname, parents' names (used for KYB checks), date and place of birth, document serial, issuing authority, issue and expiry dates, plus a confidence score and a quality breakdown that flags clarity, legibility, completeness, and lighting
  • Tax plates and trade registry documents go through AWS Textract for VKN, trade title, and tax office extraction, with table-aware parsing that survives the kind of layout Turkish official documents actually use
  • PDF uploads are converted to images client-side before they ever leave the browser, so the OCR endpoints stay format-agnostic and the heavy lifting stays off the server
  • IBANs are extracted with a layered regex set that covers spaced, continuous, and hyphenated formats, plus a fallback path that corrects common OCR character confusions, with recognition for the major Turkish banks layered on top

Name and field verification: A custom name verification engine sits between OCR output and the form values. It normalizes Turkish characters, handles common name abbreviations, and recognizes compound surnames. A similarity score is computed and mapped onto a tiered result so the system knows when to auto-approve, when to route to manual review, and when to block until an operator explicitly overrides. The same idea covers VKN and IBAN comparisons, with format checks layered on the IBAN side.

Risk team review surface: Operators see the form values and the OCR output in a side-by-side panel for every application in review. Per-document confidence scores, per-field similarity scores, and the OCR cost (token counts and dollar amount per call) are surfaced on the same screen. Operators can approve, reject with a categorized reason, or push the application into a needs-fix state with a note that the customer sees in their dashboard.

Role-aware panels and RLS: Four roles share the same database with strict separation: Admin sees and configures everything; Risk Team works the review queue; Sales Representative sees only the customers they own and can create applications on behalf of those customers; Customer sees only their own applications, documents, and contracts. Each role has its own dedicated dashboard, and the boundaries are enforced at the database through Row Level Security policies, not just in the UI.

Documents, contracts, and merchant forms:

  • Documents: identity, tax plate, trade registry gazette, signature circulars, and signed contracts, each with its own document-type record describing file constraints and the extraction schema the OCR pipeline maps into
  • Contracts: HTML templates rendered into PDFs on the server, with a clear approval lifecycle and signed-document upload back into a private storage bucket
  • Merchant forms: once an application is approved, the system generates the downstream merchant form for the operations team, complete with the client's branding, the verified field values, and embedded reference codes

Stack:

  • Next.js with the App Router and React, TypeScript end to end with Zod validation schemas
  • Supabase Postgres with Row Level Security, Supabase Auth via SSR middleware, and Supabase Storage with private buckets for documents, merchant forms, and contracts
  • Paired migration and rollback files for every schema change
  • React Hook Form with Zod resolvers for the multi-step form
  • Tailwind CSS with shadcn/ui on top of Radix primitives for the operator and customer surfaces
  • A unified OCR provider abstraction so OpenAI Vision and AWS Textract can sit side by side and be picked based on document type
  • Server-side PDF rendering for contracts and merchant forms, and client-side PDF-to-image conversion for the OCR upload path
  • Transactional email wired through a hardened provider abstraction, with a WhatsApp deep link on the customer dashboard for support contact
  • Netlify deployment on a recent Node baseline, with a strict set of security headers (HSTS, frame protection, MIME-sniffing protection, locked-down permissions policy) and cache rules disabling caching on API routes

Operations and OCR observability: OCR call metadata (model, tokens in and out, dollar cost, latency) is logged through a dedicated OCR logger so the analytics surface can show running cost per application and per merchant. Application status transitions and document decisions are persisted through the standard data model so the risk team's actions are always reconstructable.

The result is four role-scoped panels and an OCR pipeline that handles the kind of Turkish documents (with their character set, layouts, and edge cases) that off-the-shelf OCR generally does not.

Tech Stack

Next.js 15React 19TypeScriptSupabase PostgresSupabase AuthSupabase StorageRow Level SecurityOpenAI Vision APIAWS TextractPuppeteerpdfjs-distTailwind CSSshadcn/uiRadix UIReact Hook FormZodfast-levenshteinResendNetlify