A backend developer renames a field. The tests pass. It ships. Three days later the mobile app is crashing and nobody knows why.
This is how API contract drift works. It's not a discipline problem. It's a tooling problem. When nothing enforces the contract at runtime, you're relying on everyone to manually keep specs, code, and clients in sync across multiple teams and deploy cycles. That doesn't scale.
I built a validation layer into Mokapi to fix this. The idea is simple: Mokapi sits between your client and backend, validates every request and response against your OpenAPI spec, and gives you an immediate, actionable error the moment something violates the contract.
The Forwarding Script
One JavaScript file is all it takes:
import { on } from 'mokapi'
import { fetch } from 'mokapi/http'
export default async function() {
on('http', async (request, response) => {
const url = getForwardUrl(request)
if (!url) {
response.statusCode = 500
response.body = 'Failed to forward request: unknown backend'
return
}
try {
const res = await fetch(url, {
method: request.method,
body: request.body,
headers: request.header,
timeout: '30s'
})
response.statusCode = res.statusCode
response.headers = res.headers
const contentType = res.headers['Content-Type']?.[0] || ''
if (contentType.includes('application/json')) {
response.data = res.json() // triggers response validation
} else {
response.body = res.body
}
} catch (e) {
response.statusCode = 500
response.body = e.toString()
}
})
function getForwardUrl(request) {
switch (request.api) {
case 'backend-1':
return `https://backend1.example.com${request.url.path}?${request.url.query}`
case 'backend-2':
return `https://backend2.example.com${request.url.path}?${request.url.query}`
default:
return undefined
}
}
}
request.api contains the info.title from your OpenAPI spec and is used here purely for routing to the right backend URL.
The choice between response.data and response.body is what controls validation: setting response.data tells Mokapi to validate the response against the spec schema, while setting response.body skips validation entirely. So for JSON responses you want validated, use response.data. For anything else, response.body passes it through as-is.
No changes to your backend. No changes to your client. Just point the client at Mokapi instead.
What It Actually Catches
More than just a renamed field. Mokapi validates:
- Request method, URL structure, headers, query parameters
- Request body: required fields, data types, format constraints
- Response status codes, headers, and body structure
A backend that starts returning a string where the spec says number. A client sending a request body missing a required field. A response body that doesn't match the documented schema. All caught at the boundary, with a message that tells you exactly what violated what.
Where to Use It
It's the same script in every context. Between frontend and backend during local development. Between microservices in CI. In Playwright tests so your test suite becomes a contract test suite automatically. In Kubernetes preview environments before changes reach staging.
Full Walkthrough
The complete guide on mokapi.io covers the full setup.
Happy to answer questions in the comments.
Top comments (0)