Reference Fields
Reference, choice, and user fields in DealCloud return rich objects by default. This page covers how to control their format for easier processing. Resolution uses the same read pipeline as other fields (intapp-rest-client).
Default Behavior
By default, reference fields return full objects:
contacts = dc.read_data("Contact", output="list")
# Default: Full reference object
print(contacts[0]["Company"])
# {
# "id": 12345,
# "name": "Acme Corp",
# "type": 0,
# "entryListId": 2011,
# "url": "..."
# }Reference Format Options
Use ReferenceFormat to control output:
from dealcloud_sdk import DealCloud, DealCloudConfig, ReferenceFormat
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)# Full reference objects (default)
contacts = dc.read_data(
"Contact",
output="list"
# reference_format defaults to FULL
)
print(contacts[0]["Company"])
# {"id": 12345, "name": "Acme Corp", "entryListId": 2011, ...}With DataFrames
# DataFrame with name-resolved references
df = dc.read_data(
"Contact",
output="pandas",
reference_format=ReferenceFormat.NAME
)
# Easy filtering on reference values
acme_contacts = df[df["Company"] == "Acme Corp"]Reference Caching
When using ReferenceFormat.NAME, the SDK fetches display names via additional API calls. Use ReferenceCache for efficiency:
from dealcloud_sdk import ReferenceCache
# Create cache (LRU with max entries)
cache = ReferenceCache(max_entries=10000)
# First read populates cache
contacts = dc.read_data(
"Contact",
output="pandas",
reference_format=ReferenceFormat.NAME,
reference_cache=cache
)
# Subsequent reads use cached names (faster)
more_contacts = dc.read_data(
"Contact",
output="pandas",
query="{Status: 'Active'}",
reference_format=ReferenceFormat.NAME,
reference_cache=cache # Cache hits!
)
print(f"Cache size: {len(cache)}")Cache Configuration
# Default: 10,000 entries
cache = ReferenceCache()
# Smaller for memory-constrained environments
cache = ReferenceCache(max_entries=1000)
# Larger for many references
cache = ReferenceCache(max_entries=50000)Cache Methods
| Method | Description |
|---|---|
get(object_id, entry_id) | Get cached name or None |
set(object_id, entry_id, name) | Set a mapping |
bulk_set(object_id, mappings) | Set multiple mappings |
get_missing(object_id, entry_ids) | Find IDs not in cache |
len(cache) | Current cache size |
Legacy resolve Parameter
The older resolve parameter is still supported for backward compatibility, and applies to all output formats (list, polars, polars_lazy, and pandas):
# Legacy approach (still works)
df = dc.read_data("Contact", output="pandas", resolve="name")
df = dc.read_data("Contact", output="pandas", resolve="id")
# Also works for polars and list outputs
pl_df = dc.read_data("Contact", output="polars", resolve="name")
rows = dc.read_data("Contact", output="list", resolve="name")reference_format is recommended over resolve for new code. It provides more control and supports caching.
resolve is resolved locally from the reference objects already present in each row (no extra API calls), so unlike ReferenceFormat.NAME it does not perform name lookups. When both resolve and reference_format are supplied, reference_format takes precedence.
Multi-Select References
For multi-select reference fields:
# Full objects (default)
deals = dc.read_data("Deal", output="list")
print(deals[0]["Companies"])
# [
# {"id": 123, "name": "Acme Corp", ...},
# {"id": 456, "name": "Beta Inc", ...}
# ]
# IDs only
deals = dc.read_data(
"Deal",
output="list",
reference_format=ReferenceFormat.ID
)
print(deals[0]["Companies"])
# [123, 456]
# Names only
deals = dc.read_data(
"Deal",
output="list",
reference_format=ReferenceFormat.NAME
)
print(deals[0]["Companies"])
# ["Acme Corp", "Beta Inc"]Choice Fields
Choice fields behave similarly:
# Full choice objects (default)
companies = dc.read_data("Company", output="list")
print(companies[0]["Industry"])
# {"id": 101, "name": "Technology", "seqNumber": 1, ...}
# ID only
companies = dc.read_data(
"Company",
output="list",
reference_format=ReferenceFormat.ID
)
print(companies[0]["Industry"])
# 101
# Name only
companies = dc.read_data(
"Company",
output="list",
reference_format=ReferenceFormat.NAME
)
print(companies[0]["Industry"])
# "Technology"User Fields
User fields follow the same pattern:
# Full user objects (default)
deals = dc.read_data("Deal", output="list")
print(deals[0]["AssignedTo"])
# {"id": 5678, "name": "John Smith", "url": "mailto:john@example.com", ...}
# ID only
deals = dc.read_data(
"Deal",
output="list",
reference_format=ReferenceFormat.ID
)
print(deals[0]["AssignedTo"])
# 5678
# Name only
deals = dc.read_data(
"Deal",
output="list",
reference_format=ReferenceFormat.NAME
)
print(deals[0]["AssignedTo"])
# "John Smith"Performance Considerations
| Format | API Calls | Best For |
|---|---|---|
FULL | 1 | When you need all reference details |
ID | 1 | When linking to other systems |
NAME | 1 + lookups | Reports, exports, display |
Optimizing NAME Resolution
# Create cache before processing multiple objects
cache = ReferenceCache(max_entries=20000)
# Process objects that share references
for obj in ["Contact", "Deal", "Interaction"]:
data = dc.read_data(
obj,
output="pandas",
reference_format=ReferenceFormat.NAME,
reference_cache=cache # Shared cache
)
data.to_csv(f"{obj.lower()}.csv")Working with Reference IDs
When you need to use reference IDs in updates:
# Read with IDs
contacts = dc.read_data(
"Contact",
output="list",
reference_format=ReferenceFormat.ID
)
# Use IDs directly in updates
updates = []
for contact in contacts:
if contact["Company"] == 12345: # Old company ID
updates.append({
"EntryId": contact["EntryId"],
"Company": 67890 # New company ID
})
dc.update_data("Contact", updates)Related
- Basic Reads - Read operations
- Query Syntax - Filtering by references
- Schema API - Getting field metadata