Skip to main content

Vibe · Client case study · Developer Platform

Versioning Vibe’s API without duplicating the product

A TypeScript architecture built on chained adapters, enabling contract changes, code-generated documentation and the removal of an old revision without affecting later ones.

Explore the Developer Platform
Public Vibe Developer Platform portal presenting its Connected TV advertising APIs

Client case study · Freelance engagement

By Byrds ConsultingUpdated on 7 min read

At Vibe, integrations are part of the product. The consultant joined a seven-person team to work on partner connectors and the Developer Platform, with a particular focus on public API versioning.

The engagement

Expanding the partner ecosystem without splitting the codebase

Vibe enables companies to buy, manage and measure advertising campaigns on Connected TV. Its ecosystem includes integrations with products such as Clay, Fivetran, Adjust and AppsFlyer, alongside a Developer Platform that other engineering teams can use directly.

The team included one engineering manager, one product manager and five freelance full-stack developers. The engagement covered several integrations and the Developer Platform. Frontend applications used React, Next.js and TypeScript, while services were written in NestJS and Rust. The API had to cover campaigns, audiences, creatives and reporting while allowing each partner to adopt a new revision on its own schedule.

Scope

Cover authentication, documentation and testing without maintaining one copy of the product for each revision.

  • Evolve the public contract without forcing every partner to migrate at once.
  • Keep a single current implementation of the business logic.
  • Produce OpenAPI documentation from the code that is actually deployed.

Constraint

A new revision should not require a new application

A partner API usually outlives most product screens. Renaming a field, adding fields to a payload or making a value mandatory may improve the current API while breaking an integration that will not be upgraded for several months.

An ADR established the rule before implementation: contracts remain isolated by revision, adapters only translate from one revision to the next and business services only understand the current model. TypeScript surfaces type incompatibilities between those layers during type checking.

Isolated contracts

Each revision owns its input and output types. Business services use the current model, and the type checker catches incompatible contracts as they evolve.

Adjacent transformations

An old request moves from V1 to V2, then from V2 to the current model. No adapter needs to understand every revision.

Remove one revision at a time

Once V1 is deprecated and no longer receives traffic, removal covers its routes, input and output adapters, schemas, tests and documentation. V2 and later revisions remain unchanged.

Documentation kept in sync

The revision header, schemas and errors for each version are described by the OpenAPI specification produced from the same codebase.

Versioning became an explicit dependency graph. Each revision only depends on the next one, and all of them converge on the same business behaviour.

Architecture decision

Adapt every request to the current model

The partner pins the revision used for its calls with the X-Vibe-Revision header. The request is validated against that contract, then passes through a sequence of small adapters until it reaches the current format. The application service therefore receives the same type regardless of the requested revision.

Each adapter has typed input and output. If the output of V1 no longer matches the input of V2, compilation fails. This catches broken contract boundaries, but it cannot prevent inappropriate imports or deliberate type-safety bypasses on its own; module boundaries, linting and review still matter.

Versioned public contract · TypeScript

Authentication, validation and types specific to the revision requested by the partner.

Adjacent adapters · V1 → V2 → current

Small transformations whose input and output are checked by the compiler.

Current business services · NestJS / Rust

One implementation for campaigns, audiences, creatives and reporting data.

Runtime · Kubernetes / AWS / Cloudflare

Deployment and exposure of the platform behind a stable public contract.

Old revisions converge on the current model. They do not introduce a permanent branch in the business logic.
Chain two revisions to adapt an incoming requestTypeScript
type Adapter<From, To> = (input: From) => To

const v1ToV2 = ((input: V1.CreateCampaign) =>
    mapV1ToV2(input)
) satisfies Adapter<V1.CreateCampaign, V2.CreateCampaign>

const v2ToCurrent = ((input: V2.CreateCampaign) =>
    mapV2ToCurrent(input)
) satisfies Adapter<V2.CreateCampaign, Current.CreateCampaign>

const createFromV1 = (input: V1.CreateCampaign) =>
    campaigns.create(v2ToCurrent(v1ToV2(input)))

This example only covers an incoming request: creation logic receives the current contract. In production, the current response is then projected back to the output contract for the requested revision. Removing V1 requires no change to V2 or the campaigns service.

Implementation

Keep the ADR, tests, OpenAPI and public documentation aligned

Types alone were not enough. The versioning approach had to remain easy to review in pull requests, testable with dedicated accounts and understandable to a partner unfamiliar with Vibe’s internal organisation.

  1. 01

    Write the invariants in an ADR

    The document defines revision isolation, dependency direction, adapter ownership and the conditions for removing a revision.
  2. 02

    Segment contracts in the codebase

    Schemas and DTOs are organised by revision. The module layout makes cross-version imports visible, while TypeScript flags incompatible signatures.
  3. 03

    Generate OpenAPI from code

    The reference published on developers.vibe.co comes from the specification produced by the codebase. Contract and documentation updates therefore ship together.
  4. 04

    Test with controlled data

    Dedicated test accounts and injected data cover campaign, audience, creative and reporting journeys.
  5. 05

    Gate every change in CI

    GitHub Actions runs the checks before deployment to Kubernetes, AWS and Cloudflare. Every release still requires approval from a team member.

Types, tests and the OpenAPI specification keep the implementation and public documentation in sync. Team review remains the final gate before release.

Outcomes

From a few dozen to roughly one hundred partners

During the engagement, Vibe’s ecosystem grew from a few dozen to roughly one hundred partners. API versioning was not the sole cause of that growth, but the increase required an API the team could extend without coordinating a platform-wide migration for every change.

Dedicated integrations and the Developer Platform provided two complementary paths: supporting integrations with products such as Clay, Fivetran, Adjust and AppsFlyer, and enabling other partners to build directly against Vibe’s public API contracts.

What the team put in place

Concrete changes in the codebase, documentation and CI.

  • A public API covering campaigns, audiences, creatives and reporting.
  • Isolated revisions linked by TypeScript adapters checked at compile time.
  • One current business implementation shared by every active revision.
  • Partner documentation generated from OpenAPI and published on developers.vibe.co.
  • Test accounts, injected data and a GitHub Actions pipeline protecting contract changes.

The decision that held up over time

At Vibe, each API revision could still be removed independently because it was treated as an adapter to the current model, not as a permanent copy of the product.

Public sources and documentation

  1. Vibe Developer Platform. Vibe. Public platform portal and presentation of the REST APIs available to partners.
  2. API Versioning. Vibe Developer Platform. Documentation for the revision header, request pinning and compatibility policy.
  3. Vibe API Reference. Vibe Developer Platform. Public reference for campaign, creative, audience and reporting resources.
  4. Introducing the Vibe Developer Platform. Vibe. Official overview of self-serve integrations and capabilities embedded in partner products.

Is your public API becoming difficult to evolve?

Let’s define the contract, versioning strategy and CI controls before each partner requires its own compatibility branch.