Hello,
I am a developer of an application which consumes the V3 & V4 API-s.
My use case is to read all association labels data for all objects in the V3 & V4 API-s using the requests below:
Spoiler
GET /crm/v3/objects/contacts?limit=100&associations=companies,tickets,deals,quotes,tasks&archived=false HTTP/1.1
GET /crm/v3/objects/companies?limit=100&associations=contacts,tickets,deals,quotes,tasks&archived=false HTTP/1.1
…
GET /crm/v4/objects/contacts?limit=100&associations=companies,tickets,deals,quotes,tasks&archived=false HTTP/1.1
GET /crm/v4/objects/companies?limit=100&associations=contacts,tickets,deals,quotes,tasks&archived=false HTTP/1.1
…
There are 2 problems that I am facing with this scenario.
1 - The first problem
, is that I have to first fetch the object names/type ids, in order to provide the list of values to the associations query parameter. To retrieve this data, I have to make a call to the /schemas/{object} endpoint. I do this by saving every value for the toObjectTypeId property in the label definitions in a set data structure.
Spoiler
GET https://api.hubapi.com/crm/v3/schemas/contact HTTP/1.1
{
“labels”: { “singular”: “Contact”, “plural”: “Contacts” },
…
“associations”: [
{
“fromObjectTypeId”: “0-1”,
“toObjectTypeId”: “0-11”,
“name”: “CONTACT_TO_CONVERSATION”,
“cardinality”: “ONE_TO_MANY”,
“inverseCardinality”: “ONE_TO_MANY”,
“hasUserEnforcedMaxToObjectIds”: false,
“hasUserEnforcedMaxFromObjectIds”: false,
“maxToObjectIds”: 50000,
“maxFromObjectIds”: 50000,
“id”: “62”,
“createdAt”: null,
“updatedAt”: null
},
{
“fromObjectTypeId”: “0-11”,
“toObjectTypeId”: “0-1”,
“name”: “CONVERSATION_TO_CONTACT”,
“cardinality”: “ONE_TO_MANY”,
“inverseCardinality”: “ONE_TO_MANY”,
“hasUserEnforcedMaxToObjectIds”: false,
“hasUserEnforcedMaxFromObjectIds”: false,
“maxToObjectIds”: 50000,
“maxFromObjectIds”: 50000,
“id”: “61”,
“createdAt”: null,
“updatedAt”: null
},
{
“fromObjectTypeId”: “0-1”,
“toObjectTypeId”: “0-118”,
“name”: “CONTACT_TO_PAYMENT_LINK”,
“cardinality”: “ONE_TO_MANY”,
“inverseCardinality”: “ONE_TO_MANY”,
“hasUserEnforcedMaxToObjectIds”: false,
“hasUserEnforcedMaxFromObjectIds”: false,
“maxToObjectIds”: 50000,
“maxFromObjectIds”: 50000,
“id”: “470”,
“createdAt”: null,
“updatedAt”: null
}
…
}
In the example above: <0-11, 0-118, etc>.
2 - The second problem
(although I guess this is very specific to my use case), is that I want to be able to provide the users with the singular name of the associated object type for every association label. For example:
Spoiler
GET /crm/v3/objects/contacts?limit=100&associations=companies,tickets,deals,quotes,tasks&archived=false HTTP/1.1
GET /crm/v4/objects/contacts?limit=100&associations=companies,tickets,deals,quotes,tasks&archived=false HTTP/1.1
Spoiler
{
“results”: [
{
"id": "103381403171",
...
},
{
"id": "105363718492",
...
"associations": {
"courses": {
"results": \[{ "id": "437892522595", "type": "contact\_to\_course" }]
},
"companies": {
"results": \[
{ "id": "21960462656", "type": "contact\_to\_company" },
{ "id": "21960462653", "type": "contact\_to\_company\_unlabeled" },
{ "id": "21960462656", "type": "contact\_to\_company\_unlabeled" },
{ "id": "21960462657", "type": "contact\_to\_company\_unlabeled" }
]
},
"p45447734\_my\_custom\_object\_2": {
"results": \[
{ "id": "29664938156", "type": "contact\_to\_my\_custom\_object\_2" }
]
}
}
},
...
]
}
Spoiler
Id=105363718492
AssociatedObjectId=437892522595
AssociatedObjectType=Course
LabelName=contact_to_course
Id=105363718492
AssociatedObjectId=21960462656
AssociatedObjectType=Company
LabelName=contact_to_company
…
However, the API returns the names of the associated objects in plural:
Spoiler
“companies”: {
“courses”: {
, so I have to make a request to the /schemas/{object} endpoint for every object and build a map of singular-plural object names internally, which I can later use to create the results for the application’s users:
Spoiler
{
“labels”: { “singular”: “Contact”, “plural”: “Contacts” }
…
}
This means that my users will have to wait some time (call the /schemas/{object} endpoint several times and parse the data), before they are able to read any associations data.
The extra API calls to the /schemas/{objectType} make the overall user experience of the application bad. I think it would be much more convenient and efficient for HubSpot’s API consumers if the API provided objects metadata (where associations metadata is also included) in 1 call:
Spoiler
GET https://api.hubapi.com/crm/v3/schemas HTTP/1.1
GET /crm/v3/objects/contacts?limit=100&associations=companies,tickets,deals,quotes,tasks&archived=false HTTP/1.1
GET /crm/v3/objects/companies?limit=100&associations=contacts,tickets,deals,quotes,tasks&archived=false HTTP/1.1
…
I investigated whether this was possible and made some tests, but it seems the /schemas endpoint only returns metadata for user-defined HubSpot objects:
- Accounts Dashboard | HubSpot
Is there any other way through which I can read associations and objects metadata for all objects in 1 request? If not, has HubSpot considered this functionality? In that case, what would be a rough estimate about the time when it’s generally released to the public?
Note
If the server was able to detect this use case, by letting the consumer provide some special input/parameter, that would be an even better solution for the first problem. For example, a wildcard:
Spoiler
GET /crm/v3/objects/contacts?limit=100&associations=*&archived=false HTTP/1.1
GET /crm/v3/objects/companies?limit=100&associations=*&archived=false HTTP/1.1
…
GET /crm/v4/objects/contacts?limit=100&associations=*&archived=false HTTP/1.1
GET /crm/v4/objects/companies?limit=100&associations=*&archived=false HTTP/1.1
…
Note
In the examples I have provided here, I have used the plural object names in the list of values for the associations query parameter. In reality however, I do use the object type ids as I explained before.