If you’ve spent any serious time with SuiteCRM, you’ve probably hit this confusion sooner or later:
“Why does this field look different in the API than it does in the UI?”
Nine times out of ten, the answer lives in the split brain of Module Builder vs Studio. Let’s break it down.
Module Builder vs Studio: Same Goal, Very Different DNA
At a high level, both tools exist to customize the CRM. In practice, they serve very different roles.
Module Builder
- Used to create new modules (custom entities).
- Generates base PHP code, vardefs, relationships, language files.
- Intended to be deployable and upgrade-safe.
- You define fields before the module becomes “real” in the system.
Think of Module Builder as schema design time.
Studio
- Used to modify existing modules (core or custom).
- Adds or edits fields, layouts, labels, and relationships.
- Works directly on metadata overlays.
- Faster, more visual, but more implicit.
Think of Studio as runtime mutation.
Where Naming Conventions Go Off the Rails
This is where API developers start feeling confused.
Field Names in Module Builder
When you define a field in Module Builder:
- You choose a logical name (e.g.
contract_value) - SuiteCRM generates a database-safe name
- Everything is mostly predictable
Example:
contract_value
Clean, expected, consistent.
Field Names in Studio
Studio looks simpler, but it adds hidden complexity:
- Custom fields end with
_c - Some field types generate secondary fields
- Relationships create implicit link names
- Labels and field names are often conflated
Example:
- You create a “Customer” relate field
- You get:
customer_id_ccustomer_namecustomer_name_c(sometimes)- a hidden
linkfield
Which one shows up in the API?
Depends on context. 😐
How This Breaks API Development
From an API perspective (REST v4, v4_1, or custom endpoints), this split causes real pain:
1. Unstable Field Contracts
An API consumer expects:
{ "contract_value": 5000 }
But SuiteCRM responds with:
{ "contract_value_c": "5000", "contract_value_c_display": "€5,000"}
Or worse, the field doesn’t appear at all unless explicitly added to vardefs.
2. Different Names in UI vs API
- UI label: Customer
- Studio field name:
customer_name - API writable field:
customer_id_c - API readable field:
customer_name
So:
- You read one field
- You write another
- Neither matches what the user sees
That’s not just annoying, it’s error-prone.
3. Relationship Fields Are Especially Messy
Relate and link fields:
- Are not always returned by default
- May require
link_nameinstead offield_name - Often behave differently between list views and record views
This makes generic API integrations (mobile apps, middleware, ETL pipelines) much harder to build and maintain.
The Core Problem: Two Customization Layers, One API
SuiteCRM exposes one API, but:
- Module Builder defines structural truth
- Studio defines behavioral overrides
The API doesn’t clearly distinguish between the two.
So developers are forced to:
- Inspect vardefs manually
- Diff metadata files
- Test endpoints experimentally
- Hard-code field mappings (😬)
Practical Takeaways
If you’re building serious integrations on top of SuiteCRM:
- Prefer Module Builder for anything API-critical
Especially identifiers, numeric values, and foreign keys. - Document your real API field names
Not labels. Not UI names. Actual vardef keys. - Treat Studio as a presentation layer
Great for layouts. Dangerous for contracts. - Expect drift over time
A Studio change can silently break an API consumer months later.
Final Thought
SuiteCRM is powerful, but its flexibility comes at the cost of conceptual consistency.
Module Builder and Studio solve different problems, yet they share the same data surface. Until those layers are more cleanly separated, API developers will continue debugging metadata, instead of business logic.
