Building Criteo API, What We’ve Learned

Scott McCord
Criteo Tech Blog
Published in
8 min readNov 21, 2023

Our key lessons learned after building a new API ecosystem from scratch.

Cogs inside a circle, representing lessons learned.
Image generated w/ Stable Diffusion, synthesizing lessons learned.

It is now over three years since the release of the first version of Criteo’s modern public API. In case you missed what existed before, or what we built, I encourage you to look at my two previous articles in this series. In my final article, I take a closer look at the lessons we learned along the way, and at our future plans for Criteo API.

Lessons Learned from Building an API Ecosystem from Scratch

It’s hard to synthesize every lesson learned over the past three years into a digestible blog post that someone will want to read. So in lieu of pinpointing each little detail, I’ve settled on five lessons learned that I think have had an impact (sometimes positive, sometimes negative) on our journey to build an entire API ecosystem from scratch. These lessons also guide future improvements we make to the API.

So without further ado, my five lessons learned from researching the past, building the present, and looking to the future are:

Lesson 1: Providing a consistent API is easier said than done

Lesson 2: Build and release incrementally

Lesson 3: No magic wand for external SDK generation

Lesson 4: Reach the right audience in communications

Lesson 5: A system that is too open can be misused

Now let’s dive into details…

Lesson 1: Providing a consistent API is easier said than done

Puzzle pieces that are slightly malformed and don’t quite fit together.
Image generated w/ Stable Diffusion, synthesizing consistency is hard.

In my second blog post, I listed consistency as one of the four central themes of our API ecosystem. A consistent API is critical to providing a good experience for our clients.

Maintaining a consistent API, particularly with many different teams, across many different services, is a challenge that’s easy to underestimate. As our API grows and evolves, we are still seeing occasions where we have multiple models defining the same end resource. The API Guild process does a good job at catching discrepancies, but requires manual checking and so is prone to oversight.

Given how important this is, we have set ourselves an ambitious goal of developing tooling that will allow teams to define a consistent Canonical Model across their services, and even across Criteo as a whole (which is in itself made up of multiple services). This would eventually negate the need for manual checking, as our tooling would mandate that models comply to the overarching Canonical Model of a service.

Lesson 2: Build and release incrementally

Partially constructed buildings in a cityscape.
Image generated w/ Stable Diffusion, synthesizing building incrementally

When possible, build and release your API incrementally to promote early adoption of your API. A great example of this was the two Authorization workflows that we wanted to be supported by our Partner and Consent Portals: Client Credentials and Authorization Code. With these, we were able to leverage a standard (in this case OAuth2.0)’s different workflows to build incrementally.

We knew that our earliest adopters of the API would be clients who use API applications to access their own resources. In this case, the Client Credentials workflow makes a lot of sense as they typically only need to grant Consent once (to themselves), and then they’re good to go.

Client Credentials is also much simpler to implement technically. You don’t need to worry about authorization code validation or refresh tokens. The API needs to be able to exchange Client Credentials for an access token.

Given this was the simpler solution technically, and it fit the needs of our first few clients, we opted to offer this first and then develop the Authorization Code flow a few months later. This gave us the chance to get feedback from clients earlier in the process, which we included iteratively. However, this tiered approach to Authorization also comes with a cautionary tale, that I will cover in Lesson 5.

Lesson 3: No magic wand for external SDK generation

A wizard using a computer
Image generated w/ Stable Diffusion, synthesizing no magic wand for SDK generation

Shortly after the launch of Criteo API, the API Developer Experience team began work on a suite of SDKs that our clients can use to bootstrap their own API applications. These SDKs rely on Open Api Generator to generate language specific SDKs (in our case Java, Php, and Python) from an OAS file. What we thought was a quick win turned out to be a complex, and never ending bug squashing adventure.

Our biggest issue with the auto generated SDKs has stemmed from the mismatch between what’s defined in the OAS file and what the API service expects. For example, and to get a little technical, C# classes are nullable, but the generated OAS files aren’t marked so. SDKs had no conception of this, so they reject fields that in reality could be null. Also, EXAM developers may update their internal application, without updating the OAS file stored on the API Configuration service. This means that there’s a mismatch on what the SDK expects and what the application actually does.

These bugs led to a team-wide objective earlier this year where the API Developer Experience team went through, endpoint by endpoint, to identify mismatches between OAS files and EXAM behavior. Long story short, we identified so. many. bugs. Not many would cause issues for our client integrations (many were different Types being returned in errors and warnings), but they could really put in peril the quality we were aiming for.

In hindsight, doing these checks earlier in the life of Criteo API would have massively reduced the scope, and our efforts, of this exercise. The good news is that it’s better late than never, and the API Developer Experience is working on putting these validation checks into place. We will be excited, and relieved, to have them live.

Lesson 4: Reach the right audience in communications

A market space
Image generated w/ Stable Diffusion, synthesizing reaching the right audience

We have developed and now maintain several communication channels around our public API. These range from the very broad, like our documentation space at developers.criteo.com, to the very specific, like the emails we send out when there are breaking changes coming up in future versions of the API. Even though I didn’t spend much time on this topic during my last articles, these channels are vital to the health and success of the public API.

Recently, we’ve discovered area where we could clearly improve our communication channel. To give you the context, I’d like to talk a little bit more about our versioning strategy. New versions of the API are released every quarter, and with these new versions, previous versions are deprecated and then out of support. Clients using out of support versions of the endpoints should be alerted via email that they will need to upgrade to a stable version of the API. To do this, we rely on the API Organization contact email, a field the API Application developer would have supplied when they first registered their API Application on partners.criteo.com. The problem, however, is that users typically use their individual email address. If they leave their company, or toss Criteo emails into their spam folder, they’ll miss these alerts. This means that as soon as the endpoints are decommissioned, they’ll have a broken API application. It is dangerous to rely on a single point of contact (particularly when it’s just an individual!) when communicating business critical updates.

Going further, it can also be dangerous to rely entirely on automation with our communications. Just because we send these automatic email alerts, and they go to the right person, still doesn’t mean they are read. Sometimes, personal outreach to ensure the message is getting across is necessary.

These are things we are still working to improve, and have been clear lessons learned.

Lesson 5: A system that is too open can be misused

Image generated w/ Stable Diffusion, synthesizing systems can be too open (ironically with a closed door…)

API Application developers can enjoy a wide degree of flexibility when building on Criteo API. A single Application can be registered for multiple domains and perform a variety of different functions, from updating an advertising campaign to pulling analytics related to advertising performance. Sometimes though, being too flexible can be a design flaw that can lead you into trouble.

In Lesson 2 above, I highlighted the positives of building incrementally and used our two Authorization workflows as an example. Now that we have a more mature system in place, we are contending with a double edged sword of offering a flexible approach to authorization, particularly as it relates to third-parties developing API applications that are used by Criteo’s clients.

Because it’s a simpler to integrate, many of our third-parties opt to go with the Client Credentials workflow, which is typically only recommended when the API Application will only connect to a single client’s data. We find that several of our third-party partners have opted to go with this approach, even though they lose some advantages, like being able to rate limit based on a user level rather than application level. We also find that other third-parties ask Criteo clients to register an API application on partners.criteo.com themselves, and ask for their client ids and client secrets to connect to the third-party services. This brings back the chaos and challenges from our MAPI days I discussed in my first post, where credentials were being exchanged. It also makes setting up an API integration for our clients (and the Third-Parties’ clients) more cumbersome than it needs to be. The point of Criteo API is to make these types of configurations unnecessary. With the OAuth2.0 Auth Code flow, clients have to simply click twice. No copying and pasting credentials ever again.

This leads us to the conclusion that while openness and flexibility is important in our API, it is important for us to 1) keep an eye on how the API is used and 2) occasionally re-assess and adapt how existing features can be used.

API ecosystems are living things, and our work isn’t done (even if this blog series is 😀). We will continue to evolve and improve our API ecosystem, and we would love to hear from you on any questions you have when using our APIs. We are actively building on the lessons we’ve learned, particularly as we eye new ways our third-parties can connect to Criteo and to fleshing out our internal Canonical Model tooling.

Thanks for reading!

--

--