Blog: Taking Leap's API Design to the Next Level: Schema-First vs Code-First

Taking Leap's API Design to the Next Level: Schema-First vs Code-First

December 4, 2024

Dennis Ameling, Former Engineering Manager

Leap’s software-only solution allows our partners to launch and scale their own virtual power plants (VPPs), turning their energy resources into revenue. To make this possible, our team has developed an extensive API suite that makes it easy for partners to enroll their devices like battery storage, EVs, and HVAC systems into grid programs through Leap’s platform. But it doesn’t stop there: bidding, dispatching, and performance insights can all be automated using our APIs. This drives scalable operations, for both Leap and our partners.

The switch to scheme-first has allowed Leap to achieve greater consistency in our API designs, and makes it much easier to incorpoerate partner and internal feedback before building the actual APIs.

Since our teams are organized around the various aspects of the VPP operational journey mentioned above, we were looking for a way to offer a consistent experience around the various API endpoints that Leap offers to our partners. Think about naming of paths, property casing (snake_case, camelCase), etc.

All of Leap’s API endpoints are defined through industry-standard OpenAPI specifications. While that’s a great starting point, we encountered challenges in deciding between two approaches: code-first or schema-first?

❓Code-first v.s. schema first OpenAPI specs: What’s the difference?

In a nutshell, here’s the difference:

This seemingly small distinction has significant practical implications.

The practical implications: Lessons learned from code-first

At Leap, we were using the code-first approach in many of our projects. This boosted our development speed, because we could quickly build something that works, then annotate our endpoints and data models with OpenAPI annotations. We used the javalin-openapi library to then generate the OpenAPI specs for us.

However, we encountered several challenges with this approach:

// BEFORE
@get:OpenApiExample("[\"e859c532-7852-4d6e-9084-305aa78b496b\"]")

// AFTER
@get:OpenApiExample(objects = [OpenApiExampleProperty(value =\
"e859c532-7852-4d6e-9084-305aa78b496b")])

🏆 Leap's preferred solution: schema-first OpenAPI

One of our teams was already using schema-first OpenAPI specifications with the kotlin-spring code generator. This method takes your OpenAPI spec as YAML or JSON, and generates interfaces for your server - in our case, data classes and API endpoints that we could simply inherit from.

The biggest change here is that designing the API becomes one of the first steps in the process. That’s huge, because it allows you to:

Contributing to open source OpenAPI generators

While we found the kotlin-spring OpenAPI generator useful, we often prefer lighter frameworks like Javalin for the APIs Leap offers.

The challenge was that the OpenAPI generator didn’t have a generator yet for Javalin, so we took the initiative to contribute one! We’re now integrating this new generator in more projects, and we’ve been incredibly productive with this setup.

Conclusion: API quality and internal efficiency improved

We’ve been seeing these benefits from the schema-first OpenAPI approach so far:

And there you have it! This is how Leap is taking its API development to the next level. Let us know if you have any questions or feedback on this article, and stay tuned for more posts from our engineering team.