The Good and Bad of APIs and Why I Love Pipedrive’s API So Much

Clinton Skakun
Pipedrive R&D Blog
Published in
7 min readMar 29, 2018

An alarming number of software companies tend to put their APIs on the back burner. What they don’t realize is that it’s not about developing an API that does everything. It’s more about creating a consistent interface for a wide range of uses because less is more and consistency is often king. I’m sure many of us have had to spend some late nights going on wild goose chases to work around the limitations of an API.

CRMs these days aren’t islands, they are integration highways. Even small companies are integrating services across different platforms. This means one company interchanges a lot of data each day. This is why an API can’t just be passable, it has to go the extra mile and make sure it’s actually useful for the developers who are using it.

Common Poor Design Decisions Made in APIs

It’s not long until you run into an API that frustrates you and if you develop integrations or work at a SaaS company you probably already have a few under your belt.

Here are a few poor design choices I’ve noticed while working with APIs:

Missing Endpoints
This a red flag that the rest of the API is going to be a pain to use. If an API doesn’t cover all basic functionality, it’s going to be a nightmare to integrate. Thing is, the endpoints aren’t the only missing parts. If a company hasn’t released certain endpoints, it’s for a reason. That reason probably being that some data is very hard to access, meaning whatever you do pull from the existing endpoints, is going to have missing parts as well.

Poor System Design = Poor API Design
A few APIs will have odd limitations simply because they weren’t well though-out from day one.

I’ve run into APIs where one critical field could only be updated by re-creating the contact. You then need to delete the contact and create it again with the new value, only to update one field. This process creates the problem of IDs constantly changing over time, opening more room for error.

In another case, I could only modify a task within 24 hours of it being created which meant I couldn’t re-assign the task to the merged contact. As such, data loss was inevitable. The actual reasons for these limits were also never made clear so the only conclusion I came to was that a poor design decision was made years ago and changing it later would prove too problematic.

Incomplete Documentation
Most APIs we’ve integrated have decent documentation, but some don’t. Those that don’t are the ones we keep having to debug and pull down. These cases are worse than “missing endpoints” to me. Some APIs even have extra endpoints hidden away in the woodwork but are never publicly documented.

Inconsistent Data Modeling
One API I worked with would return either an object or an object-array for multi-value fields. If the multi-value field had one input, it would return an object, if it had more than one, an object-array. Shouldn’t it always be an object-array regardless of the number of inputs? I think so too.

It was this same API that also returned either an object or a string for the contact’s name. Confusing enough? I wasn’t even aware of this until the integration was already in production. It even turns out it was merely a tiny workaround that was never documented.

Fields should follow a consistent model so that they’re easy to predict. If not, it’s hard to know what’s really coming out the other side and when. Hopefully not when the integration is serving hundreds of customers.

Unfortunately, this is only scratching the surface and every API is structured a little differently which can make the abstractions we write really, really hard.

What I Look For in an API

Once my company, Dedupely, picks up an integration, we have to be in it for the long haul which is why, after integrating with a few messy APIs, we’ve decided to become a little pickier.

There are a number of boxes each new integration needs to tick before we can take them on as an integration partner:

  • Do they have create, update and delete endpoints for all items the user interacts with, in the UI?
  • Does the API paginate lists of contacts?
  • Is the data structure predictable?
  • Can we update all contact fields in one call?
  • Can we switch relation IDs across items such as tasks, notes, and other important data?
  • Giant Bonus: Merge endpoint and oAuth

And of course, documentation and everything that counters what I listed in the section above.

How Pipedrive Sets Themselves Apart

This is not an ad for Pipedrive, but I can’t help but sing their praises. Pipedrive’s API is nothing out of the ordinary from what you’d expect from an API. They have endpoints, JSON output, authentication, just like any other. The difference is that they put in that last bit of effort nearly everyone else fails to make.

Let me go over a few reasons why I think Pipedrive has done a great job in delivering their API:

There’s an Endpoint for Everything
This is the first box I tick when looking to integrate with a new CRM: Do they have endpoints for everything that exists in the user’s world?

This is important for a product like Dedupely since we need to be able to fetch items that users want to deduplicate and we also need to switch relations on merged items. Without this, users have potential data loss.

I can’t say I’ve found anything important in Pipedrive’s app that I can’t also find in the API. Every major feature you interact with in Pipedrive, exists in the API as well as every object that may be of slight importance to you. Of course, 95% of the time, you have endpoints so you can update, list, delete and create.

Proper Relationship Referencing
Merging contacts in Dedupely requires the extra step of switching relation IDs on items like Tasks, Notes, etc. Relationship referencing between objects in most APIs can become a complete nightmare. They are either over-complicated or impossible to handle without extra requests. For us, this has to be done quickly because it’s not an area we can afford to overlook.

Pipedrive handles relations with ease and they also return a relationship object along with the request if needed. For example, a Person contact has a Note and Task, the Person is the parent object, Note and Task reference their parent Person with “person_id”. This is all easily updatable.

It’s fairly simplistic and exactly how you would picture references between related objects and it’s very similar to how you’d handle one-to-many references in SQL databases.

Webhooks
Webhooks save the day for any integration that continuously needs to be synchronized. Unfortunately, most CRMs don’t support Webhooks or they do, but poorly. It’s a shame because Webhooks are not rocket science and the world is much better with them.

I’ve seen some services require the user to create webhooks manually in the dashboard. This is an extra step that most users would rather not take and it slows down the signup process.

Pipedrive allows you to create, update and delete webhooks from the API. This gives the developer more control over the user experience and takes the tedious, error-prone task out of the user’s hands.

Performance
Slow APIs, or worse yet, APIs that timeout or give 502 error responses cause a lot of havoc in our logs. We constantly see random errors come in that we have zero control over. This is not only a problem for us but also for our users.

This is another area where Pipedrive shines. Hands down, Pipedrive’s API is the fastest we’ve ever worked with. Large paginated lists can take a little time, but nothing compared to what we’ve experienced before.

In the end, there is still going to be some network lag, but we appreciate that Pipedrive has mitigated that.

Consistent Data Structures
Pipedrive’s not lazy about their data structure. There are no ugly surprises. Single fields are basic types, multiple fields are object-arrays. All of the value types stay consistent across the board.

This is probably never going to be an issue for most integration developers, but it’s one of my biggest pet peeves. For most scripting languages, this is trivial. In Javascript, if a value is a string instead of an integer, nothing horrible is going to happen. Subtleties like this in lower level languages are a bit tricker when mapping data to structs and doing type conversions. That said, most of you reading this won’t be writing integrations in C++ (and if you are, you’re far ahead of me).

A Real Marketplace
I used to hate OAuth for its complexity. I still cringe a little when I need to integrate with an OAuth service. However much I dislike it, I can’t ignore how much easier it makes the UX. With one-click installs, users don’t need to take the extra step to expose their API keys or put the wrong key in the wrong field. I’m still surprised when we get support tickets asking which API key goes where and I’ve even stumbled over this myself!

That said, using Pipedrive’s OAuth API is what gets you into their Marketplace and being in the Marketplace, as opposed to the integrations page, actually brings in faster signups. Users can install your app in one click, right from your Marketplace listing.

I was reluctant to switch over at first, but I’m happy we did. The bulk of new signups that have come in since getting on the Marketplace made it more than worth it.

Finally, Pipedrive Wins at Consistency

Like I said, Pipedrive doesn’t do anything over the top. They just get one principle right, consistency. This is why integrating Dedupely with them was more than easy.

This, of course, is not to bash on other services. I understand how hard it is to get an application running smoothly and most APIs weren’t built to scale to the level companies use integrations today. Smaller teams don’t always have the advantage of looking far ahead and seeing how their code is going to be used.

That said, I can appreciate the amount of well thought planning the Pipedrive team must have done to accomplish where they are today. While they’re not entirely perfect, they are leaps and bounds ahead of the industry.

--

--