Skip to main content
POST
/
api
/
v2.1
/
customer
/
individual
/
registration
Register individual customer
curl --request POST \
  --url https://sandbox.finhub.cloud/api/v2.1/customer/individual/registration \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --header 'User-Agent: <user-agent>' \
  --header 'X-Forwarded-For: <x-forwarded-for>' \
  --header 'X-Forwarded-From: <x-forwarded-from>' \
  --header 'X-Tenant-ID: <x-tenant-id>' \
  --header 'deviceId: <deviceid>' \
  --header 'platform: <platform>' \
  --data '
{
  "firstName": "Marcus",
  "lastName": "Jensen",
  "email": "marcus.jensen.1773494532320.cmcdd1@mediumrisk-example.com",
  "phone": "+37060012345",
  "password": "SecurePass123!",
  "matchingPassword": "SecurePass123!",
  "dateOfBirth": "1990-05-15",
  "gender": "MALE",
  "nationality": "Lithuania",
  "placeOfBirth": "Vilnius",
  "pincode": "12345",
  "roleIds": [
    "ACCOUNT_OWNER",
    "USER"
  ],
  "customerCategory": {
    "id": "fs-cat-b2c-low-001",
    "name": "Individual Standard"
  },
  "individualCustomer": {
    "tenantId": "97e7ff29-15f3-49ef-9681-3bbfcce4f6cd",
    "customerName": "Marcus Jensen",
    "person": {
      "firstName": "Marcus",
      "lastName": "Jensen",
      "email": "marcus.jensen.1773494532320.cmcdd1@mediumrisk-example.com",
      "dateOfBirth": "1990-05-15",
      "gender": "MALE",
      "nationality": "Lithuania",
      "addresses": [
        {
          "type": "HOME",
          "street": "123 Medium Risk Street",
          "city": "Compliance City",
          "state": "Vilnius County",
          "postalCode": "12345",
          "country": "Lithuania",
          "isPrimary": true,
          "id": "c3d4e5f6-a7b8-9012-cdef-123456789012"
        }
      ],
      "contacts": [
        {
          "type": "EMAIL",
          "value": "marcus.jensen.1773494532320.cmcdd1@mediumrisk-example.com",
          "isPrimary": true,
          "id": "<string>"
        }
      ],
      "id": "627e6673-0e82-40d5-a84c-55635db97fa8",
      "placeOfBirth": "Vilnius",
      "pincode": "12345"
    },
    "user": {
      "id": "<string>",
      "tenantId": "97e7ff29-15f3-49ef-9681-3bbfcce4f6cd",
      "username": "marcus.jensen.1773494532320.cmcdd1@mediumrisk-example.com",
      "email": "marcus.jensen.1773494532320.cmcdd1@mediumrisk-example.com",
      "password": "SecurePass123!",
      "status": "PENDING_ACTIVATION",
      "roles": [
        "<string>"
      ],
      "isActive": false
    },
    "categorization": {
      "id": "fs-cat-b2c-low-001",
      "name": "Individual Standard",
      "description": "Individual Standard",
      "isActive": true,
      "categoryFeatureRelations": [
        {
          "feature": {
            "id": "<string>",
            "code": "<string>"
          },
          "enabled": true,
          "parametrization": [
            {
              "name": "<string>",
              "value": "<string>"
            }
          ]
        }
      ],
      "parametrization": [
        {
          "name": "<string>",
          "value": "<string>"
        }
      ]
    }
  }
}
'
{
  "code": 200,
  "message": "B2C individual account created successfully. Redirect to activate-account page",
  "redirectUrl": "/auth/activate-account",
  "data": {
    "organization": false,
    "individual": true,
    "id": "5887c98c-b5b1-4234-b819-a4987f54aa77",
    "tenantId": "d1e2f3a4-b5c6-47d8-9e0f-1a2b3c4d5e6f",
    "customerType": "CT_PERSON",
    "customerStatus": "CS_REGISTRATION_COMPLETED",
    "categorization": {
      "active": true,
      "id": "B2CCustomerIndividual",
      "name": "B2C Individual",
      "description": "Customer categorization for B2C",
      "isActive": true,
      "categoryFeatureRelations": [],
      "parametrization": []
    },
    "person": {
      "lastName": "Jensen",
      "firstName": "Marcus",
      "id": "the2r6zaa6",
      "names": [
        {
          "type": "FIRST",
          "value": "Marcus"
        },
        {
          "type": "LAST",
          "value": "Jensen"
        }
      ],
      "dateOfBirth": "1990-05-15",
      "nationality": "LT",
      "email": "marcus.jensen@example.com",
      "contacts": [],
      "documents": [],
      "addresses": [
        {
          "type": "HOME",
          "street": "123 Medium Risk Street",
          "city": "Compliance City",
          "postalCode": "12345",
          "country": "LT",
          "isPrimary": true
        }
      ]
    },
    "user": {
      "id": "23cfc195-be4a-4e7c-88f2-ef789ae83d39",
      "email": "marcus.jensen@example.com",
      "roles": [],
      "permissions": [],
      "isActive": false,
      "requiresPasswordChange": false,
      "twoFactorEnabled": false
    },
    "notifications": [],
    "createdAt": "2026-01-12T19:21:59.019243Z",
    "updatedAt": "2026-01-12T19:21:59.019243Z",
    "consents": [],
    "organizationAssociations": []
  }
}

Individual Customer Registration

Register a new individual (B2C) customer with complete profile information, address history, and user account creation.
Endpoint: POST /api/v2.1/customer/individual/registration

Prerequisites

1

Get Categorization Hierarchy

Call GET /customer/individual/categorization/hierarchy/ to retrieve available categories and features.This returns the valid values you can use in registration.
2

Prepare Registration Data

Structure your request according to the required nested format with individualCustomer.person and individualCustomer.user.
3

Submit Registration

POST the registration request with all required fields.
The system automatically assigns the customer to the B2C Individual category. The response includes the categorization object showing the assigned category and its features.

Endpoint

POST /api/v2.1/customer/individual/registration

Headers

For complete details on authentication, compliance headers, and SDK implementation examples, refer to the Standard HTTP Headers reference documentation.
X-Tenant-ID
string
required
Tenant identifier for multi-tenant operationsExample: 97e7ff29-15f3-49ef-9681-3bbfcce4f6cd
Authorization
string
required
Bearer token for authenticationExample: Bearer eyJ0eXAiOiJKV1QiLCJh...
Content-Type
string
required
Must be application/json
Accept
string
Response format (optional — defaults to application/json)Example: application/json, text/plain, */*
X-Forwarded-From
string
required
Client/application identifier — Use this header from browser clients to identify the request source. This is CORS-safe and will not trigger preflight failures.Example: playground, web-app, mobile-app
User-Agent
string
required
Client application identifier — required by the global request filter for security analysis and device fingerprintingExample: YourApp/1.0 or Mozilla/5.0 (Windows NT 10.0; Win64; x64)
platform
string
required
Client platform identifier. Also accepted as sec-ch-ua-platformExample: web
deviceId
string
required
Unique device identifier for session tracking. Also accepted as X-Device-Id or device-idExample: 356938035643809
sec-ch-ua-platform
string
Browser client hint for OS platform (accepted alias for platform — automatically sent by modern browsers)Example: "Windows"

Request Body

The request body uses a nested structure. Do not send a flat object. All customer details must be inside the individualCustomer wrapper object.

Top-Level Fields

tenantId
string
Tenant identifier (optional at top level, also available in individualCustomer.tenantId)If not provided, will use the value from individualCustomer.tenantId or X-Tenant-ID header.
firstName
string
required
Customer’s first name (also duplicated in individualCustomer.person.firstName)
lastName
string
required
Customer’s last name (also duplicated in individualCustomer.person.lastName)
email
string
required
Customer’s email address (also duplicated in individualCustomer.person.email)Must be unique within the tenant.
phone
string
required
Phone number with country codeFormat: E.164 (e.g., +37060012345)
password
string
required
Password for the customer’s user accountSecurity Requirements:
  • Minimum 8 characters
  • Must contain uppercase and lowercase letters
  • Must contain at least one number
  • Must contain at least one special character
matchingPassword
string
required
Password confirmation (must exactly match password)
roleIds
string[]
required
Array of role identifiers for the userStandard Roles:
  • ACCOUNT_OWNER: Primary account owner
  • USER: Standard user permissions
Example: ["ACCOUNT_OWNER", "USER"]
dateOfBirth
string
Customer’s date of birth (YYYY-MM-DD format)Also duplicated in individualCustomer.person.dateOfBirthExample: "1990-05-15"
gender
string
Customer’s genderValid Values: "MALE", "FEMALE", "OTHER"Also duplicated in individualCustomer.person.gender
nationality
string
Customer’s nationality (ISO 3166-1 alpha-2 country code)Also duplicated in individualCustomer.person.nationalityExample: "LT", "US", "GB"
placeOfBirth
string
Customer’s place of birthAlso duplicated in individualCustomer.person.placeOfBirthExample: "Vilnius"
pincode
string
Customer’s PIN code (optional)Example: "12345"
customerCategory
object
Customer category assignment (optional)

Individual Customer Object

individualCustomer
object
required
Nested object containing all customer details

Code Examples

curl -X POST "https://sandbox.finhub.cloud/api/v2.1/customer/individual/registration" \
  -H "Accept: application/json, text/plain, */*" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: 97e7ff29-15f3-49ef-9681-3bbfcce4f6cd" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Forwarded-From: e2e-test" \
  -H "platform: web" \
  -H "deviceId: 356938035643809" \
  -d '{
    "firstName": "Marcus",
    "lastName": "Jensen",
    "email": "marcus.jensen@example.com",
    "phone": "+37060012345",
    "password": "SecurePassword123!",
    "matchingPassword": "SecurePassword123!",
    "dateOfBirth": "1990-05-15",
    "gender": "MALE",
    "nationality": "LT",
    "placeOfBirth": "Vilnius",
    "pincode": "12345",
    "roleIds": ["ACCOUNT_OWNER", "USER"],
    "customerCategory": {
      "id": "fs-cat-b2c-low-001",
      "name": "Individual Standard"
    },
    "individualCustomer": {
      "tenantId": "d1e2f3a4-b5c6-47d8-9e0f-1a2b3c4d5e6f",
      "customerName": "Marcus Jensen",
      "person": {
        "id": "the2r6zaa6",
        "firstName": "Marcus",
        "lastName": "Jensen",
        "email": "marcus.jensen@example.com",
        "dateOfBirth": "1990-05-15",
        "gender": "MALE",
        "nationality": "LT",
        "placeOfBirth": "Vilnius",
        "fullName": "Marcus Jensen",
        "addresses": [
          {
            "id": "6vsvy01jbzo",
            "type": "HOME",
            "street": "123 Medium Risk Street",
            "city": "Compliance City",
            "postalCode": "12345",
            "country": "LT",
            "isPrimary": true
          }
        ],
        "contacts": [
          {
            "id": "g4dh2ch831",
            "type": "EMAIL",
            "value": "marcus.jensen@example.com",
            "isPrimary": true
          }
        ]
      },
      "user": {
        "id": "uhqvq7sc80m",
        "tenantId": "d1e2f3a4-b5c6-47d8-9e0f-1a2b3c4d5e6f",
        "username": "marcus.jensen@example.com",
        "email": "marcus.jensen@example.com",
        "password": "SecurePassword123!",
        "status": "PENDING_ACTIVATION",
        "roles": ["ACCOUNT_OWNER", "USER"],
        "isActive": false
      }
    }
  }'

Advanced: Registration with Categorization

When registering medium or high-risk customers, you can include categorization with feature parametrization to define risk assessment parameters upfront. This follows the pattern used in production for sophisticated risk management.

How It Works

  1. Get Categorization Hierarchy - Call GET /customer/individual/categorization/hierarchy/
  2. Select Category - Choose appropriate category based on risk level (e.g., “MEDIUM_RISK_INDIVIDUAL”, “VERIFIED_INDIVIDUAL”)
  3. Build Feature Relations - Map category features with smart value selection
  4. Include in Registration - Add categorization object to individualCustomer

Example: Medium-Risk Customer with Categorization

curl -X POST "https://sandbox.finhub.cloud/api/v2.1/customer/individual/registration" \
  -H "Accept: application/json, text/plain, */*" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: 97e7ff29-15f3-49ef-9681-3bbfcce4f6cd" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Forwarded-From: e2e-test" \
  -H "platform: web" \
  -H "deviceId: 356938035643809" \
  -d '{
    "firstName": "Marcus",
    "lastName": "Jensen",
    "email": "marcus.jensen@example.com",
    "phone": "+37060012345",
    "password": "SecurePassword123!",
    "matchingPassword": "SecurePassword123!",
    "dateOfBirth": "1990-05-15",
    "gender": "MALE",
    "nationality": "LT",
    "placeOfBirth": "Vilnius",
    "pincode": "12345",
    "roleIds": ["ACCOUNT_OWNER", "USER"],
    "customerCategory": {
      "id": "fs-cat-b2c-low-001",
      "name": "Individual Standard"
    },
    "individualCustomer": {
      "tenantId": "d1e2f3a4-b5c6-47d8-9e0f-1a2b3c4d5e6f",
      "customerName": "Marcus Jensen",
      "person": {
        "firstName": "Marcus",
        "lastName": "Jensen",
        "email": "marcus.jensen@example.com",
        "dateOfBirth": "1990-05-15",
        "gender": "MALE",
        "nationality": "LT",
        "addresses": [
          {
            "type": "HOME",
            "street": "123 Medium Risk Street",
            "city": "Vilnius",
            "postalCode": "12345",
            "country": "LT",
            "isPrimary": true
          }
        ],
        "contacts": [
          {
            "type": "EMAIL",
            "value": "marcus.jensen@example.com",
            "isPrimary": true
          }
        ]
      },
      "user": {
        "tenantId": "d1e2f3a4-b5c6-47d8-9e0f-1a2b3c4d5e6f",
        "username": "marcus.jensen@example.com",
        "email": "marcus.jensen@example.com",
        "password": "SecurePassword123!",
        "status": "PENDING_ACTIVATION",
        "roles": ["ACCOUNT_OWNER", "USER"],
        "isActive": false
      },
      "categorization": {
        "id": "medium-risk-verified-5f8a9b",
        "name": "MEDIUM_RISK_VERIFIED_INDIVIDUAL",
        "description": "Medium risk verified individual customer",
        "isActive": true,
        "categoryFeatureRelations": [
          {
            "feature": {
              "id": "risk-assessment-3c4d",
              "code": "RISK_ASSESSMENT"
            },
            "enabled": true,
            "parametrization": [
              {
                "name": "RISK_LEVEL",
                "value": "MEDIUM"
              },
              {
                "name": "RISK_SCORE",
                "value": "55"
              },
              {
                "name": "PEP_STATUS",
                "value": "false"
              },
              {
                "name": "SANCTIONS_CHECK",
                "value": "STANDARD"
              },
              {
                "name": "MONITORING_FREQUENCY",
                "value": "WEEKLY"
              }
            ]
          },
          {
            "feature": {
              "id": "transaction-limits-7e2f",
              "code": "TRANSACTION_LIMITS"
            },
            "enabled": true,
            "parametrization": [
              {
                "name": "MONTHLY_LIMIT",
                "value": "20000"
              },
              {
                "name": "DAILY_LIMIT",
                "value": "5000"
              },
              {
                "name": "PER_TRANSACTION_LIMIT",
                "value": "2000"
              }
            ]
          },
          {
            "feature": {
              "id": "verification-requirements-9a1b",
              "code": "VERIFICATION_REQUIREMENTS"
            },
            "enabled": true,
            "parametrization": [
              {
                "name": "IDENTITY_VERIFICATION",
                "value": "REQUIRED"
              },
              {
                "name": "DOCUMENT_VERIFICATION",
                "value": "REQUIRED"
              },
              {
                "name": "ENHANCED_DUE_DILIGENCE",
                "value": "OPTIONAL"
              }
            ]
          }
        ]
      }
    }
  }'

Categorization Benefits

Why Use Categorization During Registration?
  1. Risk-Based Onboarding - Automatically apply appropriate risk controls
  2. Transaction Limits - Set limits based on customer risk profile
  3. Verification Requirements - Define required KYC/AML checks upfront
  4. Monitoring Frequency - Schedule appropriate transaction monitoring
  5. Compliance Automation - Ensure regulatory requirements are met

Smart Value Selection

The examples above demonstrate smart value selection patterns used in production:
ParameterSmart Selection LogicExample Values
RISK_LEVELMatch “MEDIUM”, “STANDARD”, or use middle valueMEDIUM, STANDARD, LOW
RISK_SCOREMatch 40-69 range for medium risk55, 50, 60
PEP_STATUSMatch “FALSE” or “NO”false, NO, NOT_APPLICABLE
SANCTIONS_CHECKMatch “STANDARD” or “PERIODIC”STANDARD, PERIODIC, DAILY
MONITORING_FREQUENCYMatch “WEEKLY” or “STANDARD”WEEKLY, STANDARD, DAILY
MONTHLY_LIMITMatch 15K-25K range for medium risk20000, 15000, 25000
Production Pattern: Always retrieve the categorization hierarchy first, then use smart value selection to build appropriate categoryFeatureRelations based on the customer’s risk profile.

Response

{
  "code": 200,
  "message": "B2C individual account created successfully. Redirect to activate-account page",
  "redirectUrl": "/auth/activate-account",
  "data": {
    "organization": false,
    "individual": true,
    "id": "5887c98c-b5b1-4234-b819-a4987f54aa77",
    "tenantId": "d1e2f3a4-b5c6-47d8-9e0f-1a2b3c4d5e6f",
    "customerType": "CT_PERSON",
    "customerStatus": "CS_REGISTRATION_COMPLETED",
    "categorization": {
      "active": true,
      "id": "B2CCustomerIndividual",
      "name": "B2C Individual",
      "description": "Customer categorization for B2C",
      "isActive": true,
      "categoryFeatureRelations": [],
      "parametrization": []
    },
    "person": {
      "lastName": "Jensen",
      "firstName": "Marcus",
      "id": "the2r6zaa6",
      "names": [
        {
          "type": "FIRST",
          "value": "Marcus"
        },
        {
          "type": "LAST",
          "value": "Jensen"
        }
      ],
      "dateOfBirth": "1990-05-15",
      "nationality": "LT",
      "email": "marcus.jensen@example.com",
      "contacts": [],
      "documents": [],
      "addresses": [
        {
          "type": "HOME",
          "street": "123 Medium Risk Street",
          "city": "Compliance City",
          "postalCode": "12345",
          "country": "LT",
          "isPrimary": true
        }
      ]
    },
    "user": {
      "id": "23cfc195-be4a-4e7c-88f2-ef789ae83d39",
      "email": "marcus.jensen@example.com",
      "roles": [],
      "permissions": [],
      "isActive": false,
      "requiresPasswordChange": false,
      "twoFactorEnabled": false
    },
    "notifications": [],
    "createdAt": "2026-01-12T19:21:59.019243Z",
    "updatedAt": "2026-01-12T19:21:59.019243Z",
    "consents": [],
    "organizationAssociations": []
  }
}

Response Fields

Success Response (data object)

FieldTypeDescription
idstringUnique customer identifier (UUID)
tenantIdstringTenant identifier
customerTypestringAlways "CT_PERSON" for individuals
customerStatusstringInitial status: "CS_REGISTRATION_COMPLETED"
individualbooleanAlways true for individual customers
organizationbooleanAlways false for individual customers
personobjectPerson details (simplified from request)
userobjectUser account details
categorizationobjectApplied customer category
redirectUrlstringNext step URL (activation page)
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp

Next Steps After Registration

  1. User Receives Activation Email
    • System sends activation email to registered address
    • Email contains activation code and link
  2. User Completes Activation
  3. KYC Verification Required
  4. Account Becomes Fully Active
    • After KYC approval, customer can perform all operations
    • Wallet is created automatically upon activation

Common Validation Errors

Password Mismatch

Error:
{
  "code": 400,
  "message": "Password and matching password do not match"
}
Solution: Ensure password and matchingPassword are identical

Duplicate Email

Error:
{
  "code": 409,
  "message": "Customer with email '...' already exists"
}
Solution: Email addresses must be unique within the tenant. Use a different email or retrieve the existing customer.

Invalid Nested Structure

Error:
{
  "code": 400,
  "message": "individualCustomer is required"
}
Solution: Ensure you’re using the nested structure with individualCustomer.person.* hierarchy. Do not send a flat object.

Missing Required Fields

Error:
{
  "code": 400,
  "message": "firstName is required in person object"
}
Solution: All fields marked as “required” must be present in the request. Check the field is in the correct nested location.

Best Practices

Recommended Flow:
  1. Validate Input - Check all required fields before sending
  2. Hash Passwords - Never log or store passwords in plain text
  3. Handle Activation - Guide user through activation process
  4. Complete KYC - Ensure verification is completed before enabling financial operations
  5. Monitor Status - Track customer status through the workflow

Password Security

  • Use strong password requirements (enforced by API)
  • Never send passwords over unencrypted connections
  • Implement password strength indicator in UI
  • Consider implementing password hashing client-side

Data Validation

// Example validation before API call
const validateRegistrationData = (data) => {
  const errors = [];
  
  // Check password match
  if (data.password !== data.matchingPassword) {
    errors.push('Passwords do not match');
  }
  
  // Validate email format
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(data.email)) {
    errors.push('Invalid email format');
  }
  
  // Validate phone format (E.164)
  const phoneRegex = /^\+[1-9]\d{1,14}$/;
  if (!phoneRegex.test(data.phone)) {
    errors.push('Invalid phone format (use E.164: +1234567890)');
  }
  
  // Check nested structure exists
  if (!data.individualCustomer || !data.individualCustomer.person) {
    errors.push('Missing required nested structure');
  }
  
  return errors;
};

API Schema Reference

For the complete OpenAPI schema specification of this endpoint, including all request and response structures, see the API Schema Mapping document.

Changelog

VersionDateChanges
v2.12026-01-13Initial release

Headers

User-Agent
string
required

Browser user agent

Example:

"Mozilla/5.0"

X-Forwarded-For
string
required

Client/application Ip address

Example:

"192.168.0.1"

X-Forwarded-From
string
required

Client/application identifier for request source tracking

Example:

"playground"

X-Tenant-ID
string
required

Tenant identifier

Example:

"97e7ff29-15f3-49ef-9681-3bbfcce4f6cd"

platform
string
required

Client platform identifier. Also accepted as sec-ch-ua-platform

Example:

"web"

deviceId
string
required

Device identifier

Example:

"e2e-test-device"

Authorization
string
required

Bearer token from admin or customer session creation

Example:

"Bearer <token>"

Body

application/json
firstName
string
required
Example:

"Marcus"

lastName
string
required
Example:

"Jensen"

email
string
required
Example:

"marcus.jensen.1773494532320.cmcdd1@mediumrisk-example.com"

phone
string
required
Example:

"+37060012345"

password
string
required
Example:

"SecurePass123!"

matchingPassword
string
required
Example:

"SecurePass123!"

dateOfBirth
string
required
Example:

"1990-05-15"

gender
string
required
Example:

"MALE"

nationality
string
required
Example:

"Lithuania"

placeOfBirth
string
required
Example:

"Vilnius"

pincode
string
required
Example:

"12345"

roleIds
string[]
required
Example:
["ACCOUNT_OWNER", "USER"]
customerCategory
object
required
individualCustomer
object
required

Response

Individual customer registered successfully

Standard API response wrapper used by all endpoints

code
integer

HTTP status code

Example:

200

data
object

Response from customer registration endpoints

message
string

Human-readable status message

Example:

"Success"