Skip to content
Dark MatterDark Matter
Cookbook

Bloomberg Enrich and Sync

Search in Bloomberg, enrich in Dark Matter, and sync to CRM workflow.

Overview

This cookbook walks through a complete research-to-operations pipeline: Bloomberg → Dark Matter → CRM. You search for positions of interest in Bloomberg (terminal or API), enrich them in Dark Matter with registry data, compliance status, and transfer restrictions, then sync the enriched data to your CRM. The pattern applies to allocators, fund administrators, and secondary market desks who need to reconcile Bloomberg holdings with Dark Matter's canonical registry and push structured data into Salesforce, HubSpot, or other CRM systems.

Step 1: Search Bloomberg

Use the Bloomberg terminal or Bloomberg API to search for positions of interest. Extract entity identifiers, issuer names, fund names, or other search criteria that you can use in the next step. The output feeds into Dark Matter enrichment.

Bloomberg API setup and search syntax depend on your Bloomberg Data License or B-PIPE subscription. Consult your Bloomberg representative for API access. For terminal-only workflows, export search results (e.g., CSV) and use issuer names or identifiers to query Dark Matter.

Step 2: Enrich in Dark Matter

Pass the Bloomberg results to the DMTR API for enrichment. Use the positions search endpoint to match entities by issuer name and retrieve full Position Objects. Dark Matter adds compliance status, transfer restrictions, valuation, vehicle class, and other canonical fields not available in Bloomberg.

const results = await dmtr.positions.search({ issuer_name: "Acme Growth Fund III" });

for (const pos of results.data) {
  console.log(pos.entity_id, pos.asset?.issuer?.name, pos.valuation?.current_mark?.value);
}
200Success
{
  "data": [
    {
      "entity_id": "meg-2026-112",
      "owner": "part-allocator-001",
      "status": "active",
      "asset": {
        "vehicle_class": "fund_lp",
        "issuer": {
          "name": "Acme Growth Fund III",
          "jurisdiction": "US-DE"
        },
        "terms_hash": "sha256:abc123..."
      },
      "valuation": {
        "current_mark": {
          "value": 2500000,
          "currency": "USD",
          "as_of": "2026-03-01",
          "provenance": "gp_mark"
        },
        "cost_basis": 2100000
      },
      "transfer": {
        "transferable": true,
        "restrictions": [
          {
            "type": "lockup",
            "expires": "2027-01-15T00:00:00Z"
          },
          {
            "type": "rofr"
          },
          {
            "type": "consent_required"
          }
        ]
      },
      "compliance": {
        "kyc_status": "cleared",
        "aml_status": "cleared",
        "accreditation_required": true
      }
    }
  ],
  "has_more": false
}

Step 3: Map to CRM schema

Map the enriched Position Objects to your CRM schema. Each CRM has different field names and data models; the table below shows a typical mapping from Dark Matter fields to common CRM equivalents.

PropertyTypeRequiredDescriptionExample
entity_idPosition__c.ExternalId__cYesUnique position identifier; use as external ID for upserts and deduplication.—
asset.issuer.nameAccount.NameYesIssuer or fund name; map to Account or Contact depending on CRM model.—
asset.vehicle_classPosition__c.VehicleClass__cNofund_lp, spv_llc, doiv_membership_interest, direct; use for filtering and reporting.—
valuation.current_mark.valuePosition__c.ValuationAmount__cNoCurrent mark-to-market value; may require currency conversion.—
statusPosition__c.Status__cYesactive, registered, encumbered, transferred; drives CRM lifecycle.—
transfer.transferablePosition__c.Transferable__cNoBoolean; indicates if position can be offered on secondary market.—
transfer.restrictionsPosition__c.Restrictions__cNolockup, rofr, gp_consent; store as multi-select or JSON.—
compliance.kyc_statusContact.KYCStatus__cNocleared, pending, failed; map to contact or deal record.—

Step 4: Sync to CRM

Push the mapped data to your CRM via its API. Use upsert semantics keyed by entity_id (or your CRM external ID) to avoid duplicates. Include an idempotency key when your CRM or proxy supports it.

const results = await dmtr.positions.search({ issuer_name: "Acme Growth Fund III" });

for (const pos of results.data) {
  await crmClient.upsert({
    object: "Position__c",
    externalId: pos.entity_id,
    data: {
      ExternalId__c: pos.entity_id,
      IssuerName__c: pos.asset?.issuer?.name,
      VehicleClass__c: pos.asset?.vehicle_class,
      ValuationAmount__c: pos.valuation?.current_mark?.value,
      Status__c: pos.status,
      Transferable__c: pos.transfer?.transferable
    }
  });
}

Use idempotency keys for CRM sync operations. If your CRM API supports Idempotency-Key, send a deterministic key (e.g., hash of entity_id + version) so retries do not create duplicate records. See Idempotency for Dark Matter's approach.

  • Pagination — Cursor-based pagination when syncing large result sets
  • Idempotency — Idempotency keys for safe retries
Edit this page on GitHub

Last reviewed: March 13, 2026

Was this page helpful?