CorebanqCorebanq Developer Docs
Products

Description

Overview

The products package provides functionality for managing banking products, their configurations, and settings. It supports various product types including funds transfers, card transactions, loan deposits, and account types with flexible settings management.

API Methods

Get All Products

GET /v1/products

Retrieves a list of all products with advanced querying, filtering, sorting, and pagination capabilities.

Each data[] entry is a ProductCatalogRead: name and description are resolved for the request’s Accept-Language (same negotiation as pre-flight). Locale maps are not returned on this endpoint.

Query Parameters

  • active - Filter by active status (boolean)
  • type - Filter by product type (string)
  • code - Filter by product code (string)
  • page - Page number for pagination (default: 1)
  • per_page - Items per page (default: 20)

Response

{
  "data": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "code": "IWT",
      "type": "transfers",
      "name": "Internal Wire Transfer",
      "description": "Transfer funds between internal accounts",
      "settings": {
        "min_amount": 100,
        "max_amount": 100000000,
        "daily_limit": 10000000,
        "fee_structure": {
          "type": "fixed",
          "fixed_amount": 0
        },
        "processing_time": "instant",
        "requires_approval": false
      },
      "active": true,
      "created_at": "2024-03-20T10:00:00Z",
      "created_by": "123e4567-e89b-12d3-a456-426614174001",
      "modified_at": "2024-03-20T10:00:00Z",
      "modified_by": "123e4567-e89b-12d3-a456-426614174001",
      "metadata": {}
    }
  ],
  "total": 15,
  "total_unfiltered": 20,
  "limit": 20,
  "offset": 0,
  "page": 1,
  "pages": 1
}

Advanced Query Parameters

  • sort - Sort field (e.g., "name", "created_at")
  • order - Sort order ("asc" or "desc")
  • search - Legacy top-level text search
  • search._text.like - Localized text search across resolved product name and description, including name_i18n / description_i18n values (example: search._text.like=Crypto w)
  • created_after - Filter by creation date
  • created_before - Filter by creation date

Get Product by ID

GET /v1/products/{id}

Retrieves detailed information about a specific product by its UUID.

Response

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "code": "IWT",
  "type": "transfers",
  "name": "Internal Wire Transfer",
  "description": "Transfer funds between internal accounts",
  "settings": {
    "min_amount": 100,
    "max_amount": 100000000,
    "daily_limit": 10000000,
    "fee_structure": {
      "type": "fixed",
      "fixed_amount": 0
    },
    "processing_time": "instant",
    "requires_approval": false,
    "supported_currencies": ["EUR", "USD", "CHF"],
    "compliance_rules": ["kyc_verification"]
  },
  "active": true,
  "created_at": "2024-03-20T10:00:00Z",
  "created_by": "123e4567-e89b-12d3-a456-426614174001",
  "modified_at": "2024-03-20T10:00:00Z",
  "modified_by": "123e4567-e89b-12d3-a456-426614174001",
  "metadata": {}
}

Get Product by Code

GET /v1/products/code/{code}

Retrieves a product by its code (e.g., "IWT", "OWT").

Get Products by Type

GET /v1/products/type/{type}

Retrieves all products of a specific type.

Supported Types

  • transfers - Wire transfers and payment routing (IWT, OWT, INT, OWN, OFR, …)
  • fx - Foreign exchange and currency conversion
  • credits - Credit facilities and lending products
  • deposits - Deposit and savings products
  • cards - Card issuance and card transaction products

Create Product

POST /v1/products

Creates a new banking product with specified configuration.

Request Body

{
  "code": "NEW",
  "type": "transfers",
  "name": "New Transfer Product",
  "description": "Custom transfer product",
  "settings": {
    "min_amount": 500,
    "max_amount": 50000000,
    "daily_limit": 5000000,
    "fee_structure": {
      "type": "percentage",
      "percentage": 0.001
    },
    "processing_time": "1-2 business days",
    "requires_approval": true,
    "supported_currencies": ["EUR", "USD"],
    "compliance_rules": ["kyc_verification", "aml_check"]
  },
  "active": true
}

Update Product

PUT /v1/products/{id}

Updates an existing product's configuration and settings.

Request Body

{
  "name": "Updated Product Name",
  "description": "Updated description",
  "settings": {
    "min_amount": 1000,
    "max_amount": 100000000,
    "fee_structure": {
      "type": "tiered",
      "tiers": [
        {
          "min_amount": 0,
          "max_amount": 1000000,
          "fixed_amount": 100
        },
        {
          "min_amount": 1000000,
          "percentage": 0.0005
        }
      ]
    }
  },
  "active": true
}

Delete Product

DELETE /v1/products/{id}

Deletes a product from the system.

Product Settings Structure

Products support flexible configuration through the settings field, which can include:

Transfer Settings

  • min_amount - Minimum transfer amount in cents
  • max_amount - Maximum transfer amount in cents
  • daily_limit - Daily transfer limit in cents
  • monthly_limit - Monthly transfer limit in cents
  • processing_time - Processing time description
  • cutoff_time - Daily cutoff time for processing
  • supported_currencies - Array of supported currency codes
  • requires_approval - Whether manual approval is required
  • auto_approve - Whether auto-approval is enabled
  • risk_level - Risk level (low, medium, high)
  • compliance_rules - Array of compliance rules to apply

Fee Structure

  • type - Fee type: "fixed", "percentage", or "tiered"
  • fixed_amount - Fixed fee in cents
  • percentage - Percentage fee (0.01 = 1%)
  • tiers - Array of fee tiers for tiered pricing
  • min_fee - Minimum fee in cents
  • max_fee - Maximum fee in cents

Quote Settings

  • quote.fx_source - Authoritative internal FX source for transfer-owned locked quote pricing. This is a server-owned product policy value (for example CRP, CMC, ECB, or CC), not a client-controlled request field.

Localised Names and Descriptions (§17)

Product name and description are locale-resolved at read time. The source of truth is stored in two JSONB columns:

  • name_i18n — locale → display name mapping (e.g. {"en": "Outbound Wire Transfer", "de": "Ausgehende Überweisung"})
  • description_i18n — locale → description mapping

Locale selection — send an Accept-Language header (BCP 47, e.g. de, fr-CH). The server picks the best match from supported locales and falls back to the tenant's configured default locale when no match is found.

Catalog read JSON (GET /v1/products list data[], GET /v1/products/{id}, GET /v1/products/code/{code}, GET /v1/products/type/{type}, and the POST / PUT response bodies) uses the ProductCatalogRead shape: name and description are always resolved strings from Accept-Language plus the tenant default — name_i18n / description_i18n are not serialized on those responses. Exception: GET /v1/products/{id} and GET /v1/products/code/{code} accept optional query include_i18n=true (1 / yes); when present and the caller has update permission on that product, the JSON body is a ProductCatalogEditorRead: same resolved fields plus name_i18n and description_i18n maps for admin tools (403 if the flag is set but update is denied). Pre-flight APIs use the same resolution rules on ProductSummary inside PreFlightResponse and ProductListResponse; those objects also expose only resolved strings, not locale maps.

Product matrix (pre-flight & list)

These customer-scoped endpoints evaluate active product matrix rules. They require a valid JWT and RBAC read on the target customer_id. The machine-readable contract lives in preflight.openapi.json alongside this file.

Client journey: discovery → transfer execution

  1. Discovery — While the user narrows products, source account, destination (own account or counterparty), channel, currency, and amount, the client calls POST /v1/products/pre-flight (and optionally POST /v1/products/list) with partial PreFlightRequest filters. The response includes transfer_params when product, source, and destination are all pinned so the UI can show allowed/deny, limits, and fee hints before the user commits.

  2. ExecutionPre-flight does not call the transfers API. When the user confirms, the client submits payment through POST /v1/transfers/finalize (OpenAPI: OpenAPI schema, schema CreatePaymentRequest). Customer transactions v2 “complete” flows that create real money movement delegate to the same finalize path internally.

The finalize JSON uses different wire names than the pre-flight filter (for example sender_id instead of source_account_id, nested recipient instead of flat destination_*, and amount.amount_minor instead of amount.amount on the wire — both represent minor-unit strings plus currency; precision is optional metadata). The server builds the same internal matrix input the pre-flight engine uses (transfers.PreFlightRequestFromCreatePayment), normalizes finalize product selection into pre-flight product_ids[] (resolving finalize product_code to a product UUID before matrix evaluation when needed), resolves the exact destination to the universal pre-flight selector destination_account_id = counterparties.cp_accounts.id when possible, runs products.ValidatePreFlightRequest, then products.PreFlightForFinalize before persisting the transfer. A matrix deny returns 422 with message code transfers_m.preflight_denied. Treat pre-flight responses as advisory for UX; the finalize request is authoritative subject to hydration, RBAC, idempotency, and quote rules.

Pre-flight filter (PreFlightRequest)Finalize body (CreatePaymentRequest)
customer_idcustomer_id
product_ids[]product_code / product_id (server normalizes finalize product selection into pre-flight product_ids[] before matrix evaluation)
source_account_idsender_id
destination_account_idExact universal destination selector (counterparties.cp_accounts.id) resolved server-side from recipient.type = account, recipient.account_id, or from the selected counterparty instrument
destination_counterparty_idCoarse counterparty filter built from recipient.type = recipient, recipient.id before exact destination normalization
channelchannel
amount (amount, currency, optional precision)amount (amount_minor, currency, optional precision) — same minor-units semantics

Pre-flight

POST /v1/products/pre-flight

Returns eligible products, counterparty-shaped sources, counterparty-shaped destinations, routes (viable channels per source-account / exact destination cp_account_id), optional transfer_params when product, source, destination, channel, and amount are pinned, and foreign_counterparties_allowed. The target customer itself is represented as its own/private counterparty row, matching the counterparties domain model. sources[] and destinations[] intentionally reuse counterparties response collection names: own_accounts[], bank_accounts[], and crypto_wallets[]. Selectable nested rows carry cp_account_type (account | bank_account | crypto_wallet), cp_account_id for follow-up pre-flight destination_account_id / route matching, products_allowed, and finalize_recipient hints that match transfers/finalize CreatePaymentRequest.recipient. transfer_params.amount echoes the normalized evaluated amount in minor units with precision metadata. Each products[] entry is a ProductSummary including route (payment | convert | deposit) for client navigation.

Product list

POST /v1/products/list

Returns products allowed for the customer scope. Embedded ProductSummary rows follow the same Accept-Language resolution rules as pre-flight and include route (payment | convert) so the client can pick the correct SPA screen.

Write (create / update)

Pass name_i18n and description_i18n objects in the request body to set locale-specific strings:

{
  "code": "OWT",
  "type": "transfers",
  "name_i18n": {
    "en": "Outbound Wire Transfer",
    "de": "Ausgehende Überweisung",
    "fr": "Virement sortant"
  },
  "description_i18n": {
    "en": "Send funds to external bank accounts via wire transfer.",
    "de": "Überweisen Sie Gelder an externe Bankkonten.",
    "fr": "Envoyez des fonds vers des comptes bancaires externes."
  }
}

The legacy top-level name / description strings are still accepted on write and are stored on their existing columns. They act as the read-time fallback when name_i18n / description_i18n is absent or has no entry for the resolved locale (no automatic copy into the JSONB map is performed at write time).

Custom Fields

  • custom_fields - Additional custom configuration as key-value pairs

Error Handling

The API returns appropriate HTTP status codes and error messages:

  • 400 Bad Request - Invalid input data or malformed request
  • 401 Unauthorized - Missing or invalid authentication
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Product not found
  • 409 Conflict - Product code already exists
  • 500 Internal Server Error - Server error

Error responses include detailed error messages in multiple languages (EN, DE, FR, IT).

On this page