SapotaCorp

API-led design: RAML, API Designer, and mocking before you build

On a recent integration for a banking client, the team that designed the API contract before anyone wrote a line of Mule code shipped weeks ahead of the one that didn't. This is a practitioner's account of doing API-led design right: RAML in Anypoint Design Center, a published Exchange asset, and a mocking service that let the mobile team build against the contract while the backend was still empty.

API-led design: RAML, API Designer, and mocking before you build

Key takeaways

  • Designing and publishing the API contract first turns sequential delivery into parallel delivery: consumers code against a mock while the backend is still empty, which on a recent banking project cut three to four weeks out of the schedule.
  • RAML's reuse machinery (data type fragments, traits, resourceTypes, and shared libraries) is what makes the spec maintainable across a family of related APIs, but the spec is only as useful as its examples, because the mocking service replays them verbatim.
  • Whether you write RAML or OAS matters less than committing the spec to Git as the single source of truth and linting it in CI; OAS wins on downstream tooling and codegen, while RAML stays cleaner inside the Anypoint ecosystem.
  • Mocks validate shape, not behavior or security, so contract tests with APIkit and integration tests against real API Manager policies remain mandatory before go-live to avoid the classic 'works on the mock, crashes on PROD' failure.

A while back I watched two integration teams at a bank approach the same kind of problem from opposite ends. One team was building a Customer Account System API to feed both the mobile app and the internet-banking web client. They wrote the Mule flows first, deployed something, and then started writing documentation so the front-end teams could integrate. By the time the mobile developers discovered a field was missing or named differently, the backend was already in QA, and every correction meant another round trip. Three or four cycles of "the doc says X but the response has Y" later, two sprints had evaporated on nothing but synchronization.

The other team flipped the order. They wrote the contract first as a RAML spec, reviewed it with the mobile lead and the core-banking folks in a single afternoon, published it to Exchange, and switched on a mocking service. The mobile team pointed their app at the mock URL and started building screens that same week. When the backend finally went live, the base URL changed and nothing else did.

That contrast is the whole argument for API-led, design-first development, and it is worth being concrete about how you actually do it in MuleSoft rather than just nodding along to the philosophy.

Why the contract comes before the code

The anti-pattern is seductive because it feels productive: write the flow, expose the endpoint, document it afterward. The problem is that the documentation is downstream of the implementation, so it drifts the moment anyone touches the code, and every consumer is blocked until the producer is finished. You end up serializing work that has no business being serialized.

Design-first inverts the dependency. The spec becomes the contract, and the implementation is just one party honoring it. Once the spec exists and everyone has agreed to it, the backend developers and the mobile and web developers all read the same document and build at the same time. Breaking changes surface in a design review, where they cost a conversation, instead of at UAT, where they cost a release. On the banking project the design review took a day or two; the old way of reconciling two teams through trial and error took the better part of two sprints.

There is a second, quieter benefit that pays off over a year rather than a sprint. When the contract lives in one place, you can reuse pieces of it. The bank had a Customer Account API today, but a Loan API and a Card API were coming. A Money type, an Address type, a pagination trait — define them once and every future API inherits them.

Writing the spec: RAML structure that survives reuse

A RAML 1.0 document starts with the obvious top matter — the #%RAML 1.0 header, a title that shows up in Exchange, a baseUri, and an HTTPS-only protocol list, which for a bank is non-negotiable. Resources are nested paths (/customers, then /{customerId}, then /accounts), methods are the HTTP verbs hanging off each resource, and parameters split cleanly into URI parameters that live in the path and query parameters that ride after the ?. None of that is surprising.

What makes RAML worth the trouble is the reuse machinery, and this is where teams either invest or pay later. The built-in type system lets you declare a Customer or an Account once in a types: block and reference it everywhere. Traits capture cross-cutting concerns — a secured trait that injects an Authorization header and the matching 401/403 responses, a paged trait that adds page and pageSize query parameters — so you apply behavior with is: [ paged, secured ] instead of copy-pasting. ResourceTypes go one level higher and capture the shape of a whole resource, parameterized with placeholders like <<itemType>>, so a "collection" resource type can be instantiated as customers, accounts, or transactions.

In Design Center this all gets organized as a fragment tree rather than one monster file. One concept per file: dataTypes/Account.raml, traits/client-id-required.raml, libraries/common-types.raml. The library is the real payoff for a multi-API estate — declare Money and Address in common-types.raml, pull it into any spec with uses: { common: libraries/common-types.raml }, and reference common.Money. Change the shape of money in one place and every API picks it up on the next rebuild. That is the difference between a spec you maintain and a spec you fight.

RAML or OAS: pick by who consumes it, not by taste

People burn a lot of energy on this and it is mostly the wrong energy. RAML, which MuleSoft created and then donated, is cleaner to read and has first-class traits, resourceTypes, and libraries. OpenAPI (OAS) — the spec formerly known as Swagger — has won the industry war decisively: Postman, Stoplight, Kong, the cloud API gateways, and OpenAPI Generator with its forty-odd target languages all speak OAS natively. Anypoint Design Center happily authors both.

The deciding question is who downstream has to read the thing. On the banking project the mobile team wanted to generate Swift and Kotlin SDKs straight from the spec, partner-facing documentation needed to render in standard Swagger UI, and a downstream API gateway only ingested OAS. RAML lost on all three, so the team made OAS 3.0 the source of truth on Git and generated RAML only when they needed to import into the Anypoint toolchain. If your world is entirely inside MuleSoft, RAML's nicer syntax is a perfectly good reason to stay with it.

One warning if you convert between the two: it is lossy. RAML traits have no OAS equivalent and get expanded inline; OAS oneOf/anyOf/allOf and discriminator-based polymorphism don't map cleanly back to RAML. Always read the output by hand after a conversion rather than trusting it. And whichever format you choose, commit it to Git and lint it in CI — Spectral for OAS, the AMF tooling for RAML. The spec is source code; treat a "quick edit in Design Center that never made it back to the repo" as the bug it is.

Mocking: the part that actually buys you the parallelism

Writing the contract is necessary but it isn't what unblocks the consumers. The mocking service is. Anypoint's mocking service reads your spec and stands up a public HTTPS endpoint — something like https://<random>.mocksvc.mulesoft.com/customer-account/v1 — that replays the example data declared in the spec. No backend code, no runtime license, a few seconds to refresh when you edit the RAML. The mobile team on the banking project pointed Postman and then their actual app builds at that URL, hard-coded it during development, and swapped it for the production base URL at the end. Because the contract was identical, there was no refactor.

The mock is smarter than a static stub. It matches route and method, validates the request body and parameters against the schema and returns a 400 if they're wrong, and picks a response by status code. When you declare multiple named examples, a consumer can force a specific one with a Prefer: example=accountFrozen header, or force an error path with Prefer: status=404. That is how the mobile team exercised the zero-balance and frozen-account screens long before any of those states existed in a database.

This is exactly why the examples are not optional decoration. The mock is only as good as the example data, and a mock full of "string" and 0 is actively harmful — the mobile developer never discovers that a VND balance needs thousands separators, or that the account number is fourteen digits, until it blows up in production. Realistic examples ("balance": { "amount": 15750000.50, "currency": "VND" }) catch formatting bugs during UI development, which is the whole point.

The trap to stay out of: a mock validates shape, never behavior or security. A POST against the mock persists nothing, and the mock waves through any token regardless of the OAuth scheme you declared. Teams that lean on mocks too long get bitten when the real backend's responses diverge from stale examples. The defenses are the boring, mandatory ones — scaffold the real flows with APIkit so it validates requests and responses against the same spec, run contract tests in CI on both sides, and do your security testing against real API Manager policies in SIT, not against the mock.

The principle worth keeping

The thing to internalize isn't RAML versus OAS or which toggle enables the mock. It's that an agreed, version-controlled contract is the cheapest place to discover you're wrong, and a mock built from that contract is what converts agreement into teams shipping in parallel. Design the spec, review it before anyone writes a flow, publish it, mock it — and treat the mock as a development convenience that you retire the day the real backend is ready, never as a substitute for the tests that prove the implementation actually honors the contract.


Building or operating MuleSoft integrations? Our Salesforce team designs API-led architectures, builds Mule flows, and runs them in production. Get in touch ->

See our full platform services for the stack we cover.

Contact Us Now

Share Your Story

We build trust by delivering what we promise – the first time and every time!

We'd love to hear your vision. Our IT experts will reach out to you during business hours to discuss making it happen.

WHY CHOOSE US

"Collaborate, Elevate, Celebrate where Associates - Create Project Excellence"

SapotaCorp beyond the IT industry standard, we are

  • Certificated
  • Assured quality
  • Extra maintenance

Tell us about your project