Skip to main content

Common Data Types

This document describes common data structures used throughout the FinHub API. All endpoints follow these conventions unless explicitly documented otherwise.
Purpose: Standard data structures used across all FinHub API endpoints.Use these schemas for consistent request/response formatting.

BaseResponse<T>

All API responses are wrapped in this standard structure:
interface BaseResponse<T> {
  code: number        // HTTP status code (200, 201, 400, 404, etc.)
  message: string     // Human-readable message
  data: T            // The actual response payload (generic type)
}

Success Response Example

{
  "code": 200,
  "message": "Success",
  "data": {
    "userId": "5887c98c-b5b1-4234-b819-a4987f54aa77",
    "email": "[email protected]",
    "status": "ACTIVE"
  }
}

Error Response Example

{
  "code": 400,
  "message": "Prepared order not found: prepared-order-123",
  "data": {
    "error": "Prepared order not found: prepared-order-123"
  }
}
Important: Never expect direct data in responses. All responses are wrapped in BaseResponse.Incorrect:
{ "userId": "123" }
Correct:
{ "code": 200, "message": "Success", "data": { "userId": "123" } }

AmountDto

Financial amounts use scaled integers to avoid floating-point precision issues.
AmountDto {
  value: string       // Scaled integer as string (e.g., "5000000")
  scale: number       // Number of decimal places (e.g., 2)
  currency?: string   // ISO 4217 currency code (e.g., "EUR")
}

How It Works

The value field contains the amount multiplied by 10^scale:
  • €50,000.00 = { "value": "5000000", "scale": 2, "currency": "EUR" }
  • €100.00 = { "value": "10000", "scale": 2, "currency": "EUR" }
  • €0.01 = { "value": "1", "scale": 2, "currency": "EUR" }

Examples

Request with Amount

{
  "amount": {
    "value": "5000000",
    "scale": 2,
    "currency": "EUR"
  },
  "description": "Incoming SEPA transfer"
}

Response with Amount

{
  "code": 200,
  "message": "Success",
  "data": {
    "preparedOrderId": "666f111b-20fd-4756-b610-3ee24938e96a",
    "summary": {
      "amount": 100,
      "currency": "EUR",
      "totalAmount": 100
    }
  }
}
Why Scaled Integers?Floating-point numbers (like 1000.00) can cause precision errors in financial calculations. Scaled integers ensure exact arithmetic:
  • Addition: "1000" + "500" = "1500"
  • Subtraction: "1000" - "500" = "500"
  • Comparison: "1000" > "500" = true
Common Mistake:Incorrect (using float):
{
  "amount": {
    "value": 1000.00,
    "currency": "EUR"
  }
}
Correct (using scaled integer):
{
  "amount": {
    "value": "100000",
    "scale": 2,
    "currency": "EUR"
  }
}

AddressDto

Physical address structure used for customer registration and KYC.
AddressDto {
  id?: string                // Optional ID for existing addresses
  type: AddressType          // "HOME" | "WORK" | "BILLING" | "SHIPPING"
  street: string             // Street address
  city: string               // City name
  postalCode: string         // Postal/ZIP code
  country: string            // ISO 3166-1 alpha-2 country code
  state?: string             // State/Province (optional)
  building?: string          // Building name/number (optional)
  apartment?: string         // Apartment/Unit number (optional)
  isPrimary: boolean         // Whether this is the primary address
}

Example

{
  "id": "6vsvy01jbzo",
  "type": "HOME",
  "street": "123 Medium Risk Street",
  "city": "Compliance City",
  "postalCode": "12345",
  "country": "LT",
  "isPrimary": true
}

Address Types

TypeDescription
HOMEResidential address
WORKBusiness/office address
BILLINGBilling address for invoices
SHIPPINGDelivery/shipping address

ContactDto

Contact information (email, phone, etc.) for customers.
ContactDto {
  id?: string                // Optional ID for existing contacts
  type: ContactType          // "EMAIL" | "PHONE" | "MOBILE" | "FAX"
  value: string              // Contact value (email address, phone number, etc.)
  isPrimary: boolean         // Whether this is the primary contact method
  verified?: boolean         // Whether this contact has been verified (optional)
}

Example

{
  "id": "g4dh2ch831",
  "type": "EMAIL",
  "value": "[email protected]",
  "isPrimary": true,
  "verified": true
}

Contact Types

TypeDescriptionFormat Example
EMAILEmail address[email protected]
PHONELandline phone+37060012345
MOBILEMobile phone+37067890124
FAXFax number+37060012399

PersonDto

Personal information for individual customers, directors, shareholders, etc.
PersonDto {
  id?: string                // Optional person ID
  firstName: string          // Given name(s)
  lastName: string           // Family name(s)
  middleName?: string        // Middle name(s) (optional)
  email: string              // Primary email address
  dateOfBirth: string        // ISO 8601 date (YYYY-MM-DD)
  nationality: string        // ISO 3166-1 alpha-2 country code
  gender?: Gender            // "MALE" | "FEMALE" | "OTHER" (optional)
  placeOfBirth?: string      // Birth city/location (optional)
  fullName?: string          // Full name display (optional)
  addresses?: AddressDto[]   // Array of addresses
  contacts?: ContactDto[]    // Array of contact methods
  documents?: DocumentDto[]  // Array of identity documents (optional)
}

Example

{
  "id": "the2r6zaa6",
  "firstName": "Marcus",
  "lastName": "Jensen",
  "email": "[email protected]",
  "dateOfBirth": "1990-05-15",
  "nationality": "LT",
  "gender": "MALE",
  "placeOfBirth": "Vilnius",
  "fullName": "Marcus Jensen",
  "addresses": [
    {
      "type": "HOME",
      "street": "123 Medium Risk Street",
      "city": "Compliance City",
      "postalCode": "12345",
      "country": "LT",
      "isPrimary": true
    }
  ],
  "contacts": [
    {
      "type": "EMAIL",
      "value": "[email protected]",
      "isPrimary": true
    }
  ]
}

TelephoneNumberDto

Telephone number with metadata (used for organizations).
TelephoneNumberDto {
  number: string             // E.164 format phone number
  country: string            // ISO 3166-1 alpha-2 country code
  phoneType: number          // 0=UNKNOWN, 1=MOBILE, 2=LANDLINE
  operator?: string          // Telecom operator (optional)
  purpose?: string           // Purpose (e.g., "personal", "business")
  isPrimary: boolean         // Whether this is the primary number
}

Example

{
  "number": "+37060012345",
  "country": "LT",
  "phoneType": 1,
  "operator": "Telia",
  "purpose": "personal",
  "isPrimary": true
}

Standard HTTP Headers

Request Headers

All API requests should include these headers:
HeaderRequiredDescription
X-Tenant-IDYesTenant identifier
AuthorizationYesBearer token from session login
Content-TypeYesapplication/json
AcceptOptionalapplication/json (default)
X-Session-IdConditionalRequired for transfer operations
X-User-IDConditionalRequired for some admin operations
X-User-RolesConditionalComma-separated roles for authorization

Example Request Headers

curl -X POST "https://api.finhub.cloud/api/v2.1/customer/individual/registration" \
  -H "X-Tenant-ID: tenant_cloudvault" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJh..." \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ ... }'

Standard Error Responses

400 Bad Request

{
  "code": 400,
  "message": "Missing required role 'ADMIN_USER' for BUSINESS_TYPE_CLIENT_TO_TENANT organization. At least one employee must have this role.",
  "data": {
    "error": "Missing required role 'ADMIN_USER'"
  }
}

403 Forbidden

{
  "code": 403,
  "message": "Access denied"
}

404 Not Found

{
  "code": 404,
  "message": "Unable to find matching target resource method",
  "data": {
    "error": "Unable to find matching target resource method"
  }
}

500 Internal Server Error

{
  "code": 500,
  "message": "Internal server error",
  "data": {
    "error": "An unexpected error occurred"
  }
}

Enums Reference

Gender

enum Gender {
  MALE = "MALE",
  FEMALE = "FEMALE",
  OTHER = "OTHER"
}

AddressType

enum AddressType {
  HOME = "HOME",
  WORK = "WORK",
  BILLING = "BILLING",
  SHIPPING = "SHIPPING"
}

ContactType

enum ContactType {
  EMAIL = "EMAIL",
  PHONE = "PHONE",
  MOBILE = "MOBILE",
  FAX = "FAX"
}

CustomerType

enum CustomerType {
  CT_PERSON = "CT_PERSON",
  CT_ORGANIZATION = "CT_ORGANIZATION"
}

CustomerStatus

enum CustomerStatus {
  CS_REGISTRATION_COMPLETED = "CS_REGISTRATION_COMPLETED",
  CS_PENDING_ACTIVATION = "CS_PENDING_ACTIVATION",
  CS_ACTIVE = "CS_ACTIVE",
  CS_SUSPENDED = "CS_SUSPENDED",
  CS_CLOSED = "CS_CLOSED"
}

Date and Time Formats

All dates and times use ISO 8601 format:
TypeFormatExample
DateYYYY-MM-DD2026-01-13
DateTimeYYYY-MM-DDTHH:mm:ss.SSSZ2026-01-13T19:21:47.631Z
DateTime (with timezone)YYYY-MM-DDTHH:mm:ss.SSS+HH:mm2026-01-12T22:21:56.903+03:00

Examples

{
  "dateOfBirth": "1990-05-15",
  "createdAt": "2026-01-12T19:21:59.019243Z",
  "expiresAt": "2027-01-12T22:21:53.254059600"
}

Pagination (Future)

Pagination is not yet implemented in v2.1. All list endpoints currently return complete results. Future versions will support cursor-based pagination.

Validation Rules

Email Format

Phone Number Format

  • Must use E.164 format
  • Example: +37060012345

Country Codes

  • Must use ISO 3166-1 alpha-2 (2-letter codes)
  • Examples: LT, GB, DE, US

Currency Codes

  • Must use ISO 4217 (3-letter codes)
  • Examples: EUR, USD, GBP