400 Bad Request When creating company via API


#1

Hi all,

I'm trying to add a company via the API to my developer HUB (5217770).

This is my json:

{"properties":[
{"property":"name","value":"A company name"},
{"property":"description","value":"A company descriptioN"}
]}

I'm POSTing to https://api.hubapi.com/companies/v2/companies/?hapikey=XXX, i'm setting media type to "application/json", encoding is UTF-8.

This is the response i'm getting:

StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1,
Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent,
Headers:{
Date: Thu, 20 Dec 2018 18:00:44 GMT
Connection: keep-alive
X-Trace: 2B218286867A12037BD6EE3ECD2861E24FDA09E7AC000000000000000000
X-HubSpot-RateLimit-Daily: 40000
X-HubSpot-RateLimit-Daily-Remaining: 39982
X-HubSpot-RateLimit-Secondly: 10
X-HubSpot-RateLimit-Secondly-Remaining: 9
Access-Control-Allow-Credentials: false
Strict-Transport-Security: max-age=31536000;
includeSubDomains; preload
Expect-CT: max-age=604800,
report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 48c4029c0fc167c7-EZE
Content-Type: application/json;
charset=utf-8
Content-Length: 387
}

Any ideas on what could be wrong? Thanks.


#2

Adding more piece of context, i have code whose guts are exactly the same working fine for creating contacts.
Same base logic, just changing the API endpoint, and the JSON payload i'm posting.


#4

Hey, @nraddatz.

Happy to clarify.

While the Contacts API accepts JSON fields with the format:

 {
      "property": "",
      "value": ""
}

The Companies API uses:

{
      "name": "",
      "value": ""
}

I successfully created this company in your test account with the following body:

{
  "properties": [
    {
      "name": "name",
      "value":"Developer Support Test Company 1"
    },
    {
      "name": "description",
      "value": "This company is a test."
    }
  ]
}

#5

Thanks so much! It was a subtle, yet important difference. With your help i got my code working as expected.

As a constructive suggestion...it would be really nice if there was consistency across the different APIs. In my travels implementing an integration between hubspot and a CRM, i've found other subtle differences like this one that make it very hard to implement generic functions that will work across different HubSpot endpoints.

For example, most feeds with paging have a "has-more" property to know if there are more results...but the "/email/public/v1/campaigns/by-id" feed has a "hasMore" property (note no dash, camelcase) instead. As a result, instead of having generic code, i needed to write specific logic to handle one scenario or the other.

Hope this makes sense.


#6

Thanks for the feedback, @nraddatz! I couldn't agree more.

We're actually in the middle of auditing all our developer documentation; I'll make sure to record your comment.

The audit is part of a much larger effort to enhance the consistency and ease-of-use of our APIs and to improve the developer experience. @Connor_Barley and I are on the front lines of this movement, so we welcome comments like these!


#7

@Isaac_Takushi and @Connor_Barley: Great! Sounds like a definite step forward. The more consistent the APIs are, the easiest it will be for developers to implement maintainable, robust integrations with your product.

Given that you are at that, i may suggest a few more enhancements:

  • All APIs should support sorting - for example, events are always returned in reverse chronological order, which makes it unnecessarily hard to implement integrations where you need to keep records in sync between HubSpot and external systems. If i was able to sort by date ascending, i can basically just keep a "pointer" of the last successfully retrieved record, and on each sync cycle use it to just download the "delta" of records (any records created after that one). With reverse chronological order, the algorithms to make sure you have everything in sync are a lot harder to implement.
  • All objects should expose created and modified timestamp. Again, for synchronization purposes, it is a lot easier to track the "delta" of changes based on timestamp. As an example, if i want to synchronize email campaigns, the only way i currently have, is to first get the entire list of campaign ids ("/email/public/v1/campaigns/by-id" endpoint), and then for each campaign get the campaign details, and then check if i have already synchronized it or not via manual checks. It would be a lot easier if i could just say "give me all campaigns where createdate > x".

Hope the above suggestions make sense.


#8

@Isaac_Takushi and @Connor_Barley: I just found another inconsistency. In order to update a contact, a POST must be sent to the server (https://developers.hubspot.com/docs/methods/contacts/update_contact), but, in order to update a company, a PUT must be sent to the server (https://developers.hubspot.com/docs/methods/companies/update_company)...again this makes it very difficult to implement generic, robust integrations, as you have to deal with specific scenarios in code, instead of having the ability to implement parametric functions. Also, from my tests it looks like, when you update a contact, the api returns nothing back...but when you update a company, the api actually returns the updated record.

Thanks for your attention.


#9

Thanks again for the feedback, @nraddatz.

I too have encountered these inconsistencies before, and I agree they should be improved.

Historically speaking, I believe these mismatches were the result of different product teams owning and updating various APIs. As we shift our mindset to consider HubSpot "one platform," though, we'll be smoothing these kinds of rough edges and standardizing the development experience.