Mock REST APIs Skill
SkillDev toolsLets your agent create a mock REST API endpoint so you can test integrations without the real third-party service.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Mock REST APIs Skill skill
About this capability
Stand up an HTTP endpoint you control instead of a live third-party API, and point the Mendix app at it, Prism from an OpenAPI contract, a constant swap, or a forward proxy. Use when building or debugging a REST integration without the real API, forcing a 404/500 through an error handler, or runnin
What this skill tells your AI
The instructions your AI receives, as published by mendixlabs/mxcli in .claude/skills/mendix/mock-rest-apis/SKILL.md and read by ahel’s review.
Use this skill when a REST integration needs an endpoint you control instead of a live third-party API — while building it, while reproducing a bug, or while verifying the app in a browser or a test run.
Developing against the real API means network, rate limits, credentials, and a payload that can change under you. None of that is where Mendix integration defects live: those are in the mapping, the entity types, the error handler, and the BSON. A mock removes the variables that are not the bug.
When to Use This Skill
- Building a REST client or
REST CALLmicroflow before (or without) real credentials - Reproducing a payload-shaped bug deterministically — a shape small enough to read, that behaves the same on every run
- Exercising error paths: 404, 500, a timeout, a 401 from missing auth
- Verifying the app (
test-app) or running a suite (test-microflows) offline or in CI - Redirecting the outbound calls of an app whose model you must not edit
Two separate problems
Almost every wasted hour here comes from conflating them:
| Problem | Answer |
|---|---|
| Something must answer the request | A mock server: Prism (from a contract), WireMock, mitmproxy |
| The app must send the request there | A constant, a BaseUrl, or a forward proxy — see below |
A mock server is not an interceptor. Prism serves one contract at one port and answers only clients that address it. Asking it to "catch all calls the app already makes" is a category error — that is the forward-proxy job, further down.
1. Point the app at the mock
Three routes, cheapest first. Pick by how the URL is built.
The URL is built in the microflow — use a constant, change nothing per run
A REST CALL URL is an expression, so it can be assembled from a constant
(@Module.Constant is Mendix's constant reference — $Name is a variable):
create constant MyModule.ApiBaseUrl type String default 'https://api.example.com/v1';
create microflow MyModule.CallApi() returns string
begin
$response = rest call get @MyModule.ApiBaseUrl + '/rates'
header Accept = 'application/json'
returns string;
return $response;
end;
Then swap the endpoint per run, with no model change and nothing committed:
# this run only — never written to the project
mxcli run --local -p app.mpr --constant MyModule.ApiBaseUrl=http://127.0.0.1:4020
# a test suite against the mock (--constant needs --local)
mxcli test tests/ -p app.mpr --local --constant MyModule.ApiBaseUrl=http://127.0.0.1:4020
# machine-local default, gitignored: every run picks it up
mxcli constant set MyModule.ApiBaseUrl http://127.0.0.1:4020 -p app.mpr
# flip it on an app that is already running
mxcli constant set MyModule.ApiBaseUrl http://127.0.0.1:4020 -p app.mpr --apply
constant set refuses a name the project does not define, so a typo cannot
silently apply to nothing. mxcli constant list -p app.mpr shows the winning
value for every constant and which layer set it — read it first whenever a
run does not use the endpoint you expected.
The call goes through a REST client document — rewrite BaseUrl
A REST client document's BaseUrl is a literal; it cannot reference a
constant. Point it at the mock by re-running the create, which is a one-line diff:
create or modify rest client MyModule.RatesAPI (
OpenAPI: 'specs/rates.json',
BaseUrl: 'http://127.0.0.1:4020'
);
BaseUrl also overrides servers[0].url at import time, so one contract can be
imported against the mock and later re-pointed at production.
You cannot edit the model at all — use a forward proxy
See §3. This is the most work and the last resort.
2. Prism: serve an OpenAPI contract as a mock
npm install -g @stoplight/prism-cli # ~15s
prism mock specs/rates.json --port 4020 # serves the contract's `example` values
Everything below cost real time to find out and is not on Prism's front page:
- Prism mounts paths at the root and ignores any base path in
servers[0].url. Address it ashttp://127.0.0.1:4020, nothttp://127.0.0.1:4020/v1— otherwise every path 404s while the server looks perfectly healthy. - Make
servers[0].urlabsolute in the contract you import. mxcli's OpenAPI import only accepts anhttp://orhttps://URL asBaseUrl; a relative one (/api/v3) is skipped with the warning "server URL … is relative and cannot be used as BaseUrl; set BaseUrl explicitly in CREATE REST CLIENT", and a client with noBaseUrlfails at call time, not at import time. Prefer: code=404on the request forces any status the contract documents. This is the only practical way to drive a Mendix error handler through a real HTTP response rather than by hand-editing the model.prism mock -dreturns schema-generated random data instead of theexamplevalues. Run the suite both ways: a mapping that quietly depends on one fixed payload passes underexampleand fails under-d.- Prism enforces the contract's
security, so a call with noAuthorizationheader gets a real 401. Useful — but know the ceiling before you design around it: a REST client document's header value may be a literal, a$Variable, or a literal prefix plus a variable ('Bearer ' + $Token), and nothing else. A token that must be computed per call belongs in aREST CALLexpression, not in the document. - Cut a subset; never point Prism at a vendor's full contract. The official Microsoft Graph spec is 41 MB of YAML: it downloads in seconds and Prism was still printing "Starting Prism…" when killed at a 300-second cap. Importing it would also generate thousands of operations into the module.
A contract small enough to read is the point. Hand-cut one path with one
example per response code you care about, and keep it in the project under
specs/ next to the .mpr — the same relative path the OpenAPI: clause takes.
3. Forward proxy: when the model cannot change
For an app whose model you must not touch, redirect the JVM instead. The Mendix
runtime honours the standard Java proxy properties, and mxcli run --local
passes your environment through to the runtime JVM — including JAVA_TOOL_OPTIONS,
which mxcli appends to rather than replaces, so an exported value survives
even alongside --trace. No model change, nothing committed:
export JAVA_TOOL_OPTIONS="-Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080"
mxcli run --local -p app.mpr
Two things to know before committing to this route:
- HTTPS is the real work. The proxy must present a certificate the JVM
trusts. WireMock 3.13.2 on Java 21 cannot generate a usable one; use mitmproxy
(which ships a CA you install into the JVM truststore) or supply your own
keystore. Plain
http://targets need none of this — one more reason to have the mock on loopback HTTP. - Loopback is not proxied.
127.0.0.1sits in the runtime'shttp.nonProxyHosts, so app→mock traffic on loopback works inside a proxied container without any exemption of your own. It also means a proxy on127.0.0.1will not intercept loopback calls — that is not a bug to hunt.
For consumed OData services specifically there is a fourth route that needs
no JVM flags: System.ConsumedODataConfiguration carries ProxyConfiguration,
ProxyHost and ProxyPort as data (see system-module), so the proxy can be
set per service at runtime.
Verify the mock before blaming Mendix
Always prove the endpoint from the shell first. A Mendix error message cannot distinguish "the mock is not running" from "the mapping is wrong".
curl -sS -i http://127.0.0.1:4020/rates # 200 + the example payload?
curl -sS -i -H 'Prefer: code=404' http://127.0.0.1:4020/rates
Then, and only then, run the microflow and check the payload actually reached it
(mxcli oql, or the runtime log under mxcli run --local).
Failure modes, symptoms first
| Symptom | Cause | Fix |
|---|---|---|
| Every path 404s, server looks fine | The client address includes the contract's base path | Address Prism at the root: http://127.0.0.1:4020 |
Import produced a client with no BaseUrl | servers[0].url is relative — mxcli warned and skipped it | Make it absolute, or pass BaseUrl: explicitly |
| Prism never finishes starting | Vendor contract is tens of MB | Cut the paths you need into a small contract |
| Mock returns 401 | The contract declares security; the call sent no credentials | Add the header, or drop security from your cut contract |
| Calls still reach the real API | Proxy properties not applied, or the target is loopback (never proxied) | Check the JVM args; prefer the constant route over a proxy |
| Endpoint swapped but the app disagrees | An override on a different layer wins | mxcli constant list -p app.mpr — it names the layer |
Works with example values, fails in CI | The mapping depends on one fixed payload | Run prism mock -d locally and fix the mapping |
Related Skills
rest-client— the three ways to call a REST API; where the contract goes once you have onerest-call-from-json— JSON structure → entities → import mapping →REST CALLtest-app— browser verification; a REST app's prerequisite is a reachable endpointtest-microflows— running a suite;--constantpoints it at the mockrun-local—mxcli run --local, the warm loop the mock plugs into
Signals
- GitHub stars
- 122
- Forks
- 49
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
mock-rest-apis- Source
- github.com/mendixlabs/mxcli