← All guides

Mock APIs for Power Automate β€” test HTTP actions, retry policies, run-after branches, and custom connectors

A Power Automate cloud flow that calls an external API is hard to test honestly. The API you call in production is exactly the one you don't want your test runs hitting β€” and it won't return a 503 on cue, so the retry policy, the timeout, and every Configure run after error branch ship unexercised.

Power Automate's built-in answer is static results (the yellow-beaker Static result toggle, still in preview): an action pretends to succeed with a canned payload and never executes. Genuinely useful for protecting real records while you shape downstream logic β€” and, because the action never runs, the HTTP layer is skipped entirely: retries, timeouts, 429s, and failure branches never fire. This guide covers the other half: a live, stateful mock API your HTTP actions can actually call, that fails exactly when you tell it to. Every curl below was verified against production before publishing.

Licensing, honestly: the HTTP action, the When an HTTP request is received trigger, and custom connectors are all premium in Power Automate β€” you need a Premium license (or trial) to use them at all. Microsoft's free Developer Plan gives you a dev environment where you can build and test with premium connectors. Mockbird doesn't change any of that; it gives the premium actions you're already licensed for something safe to call.

1. A stand-in API for the HTTP action

The public demo project is a seeded e-commerce API. Add an HTTP action, method GET, URI:

https://mockbird.mockbird.workers.dev/m/demo/products?limit=2

Run the flow β€” body() is two product records, ready for a Parse JSON action (generate the schema from a sample by pasting the response). Writes work too: POST /m/demo/products with a JSON body creates a record a later action can GET back. Standard query conventions (_page/_limit/sortBy/field filters, json-server compatible) make Do until pagination loops testable. Want your own schema instead of ours? One curl or one click, below.

2. A custom connector from a live OpenAPI URL

Every Mockbird project publishes its schema as OpenAPI at /m/<project>/openapi.json. In Power Automate: Custom connectors β†’ New custom connector β†’ Import an OpenAPI from URL, and paste:

https://mockbird.mockbird.workers.dev/m/demo/openapi.json

You get a connector with typed list/get/create/update/delete operations per resource β€” no premium-API sandbox account, no hand-written swagger. The export is OpenAPI 3.0.3; Power Platform's connector wizard imports OpenAPI definitions and accepts v3 specs directly since Microsoft's 2025 release wave 2 (older tenants may still want a v2 file β€” the wizard will say so on import). This is also the cheap way to rehearse the connector-building workflow itself before you point it at a real internal API.

3. Prove the retry policy actually retries β€” deterministically

The HTTP action's Settings β†’ Retry Policy defaults to exponential, 4 retries, and fires only on 408, 429, and 5xx. The problem is proving any of that: real APIs don't fail twice and then recover on cue. ?mock_seq does exactly that:

# 1st request β†’ 503, 2nd β†’ 503, 3rd and later β†’ real 200 response
curl -s -o /dev/null -w '%{http_code}\n' \
  'https://mockbird.mockbird.workers.dev/m/demo/products?mock_seq=503,503,200&mock_seq_key=myflow'
# run it four times: 503 503 200 200

Point the HTTP action at that URL and run the flow once: attempts one and two eat the 503s, attempt three succeeds, the action goes green β€” and the run history shows each retry. Every response carries x-mockbird-seq: pos/len so you can see which step of the sequence each attempt hit. Now change the sequence to mock_seq=404,200 and watch the action fail immediately β€” 4xx (other than 408/429) is not retryable, a distinction worth seeing once before you rely on it. Use a distinct mock_seq_key per flow so parallel tests don't share a counter, and &mock_seq_reset=1 to restart a sequence. Failed writes are not applied β€” a POST that draws a 503 inserts nothing, which is exactly the semantics your retry logic should assume.

4. Fire your error branches from a URL param

Failure handling in Power Automate is Configure run after β€” a parallel branch (or Scope) set to run when the previous action has failed or has timed out. Those branches usually get tested by hoping something breaks. Make it break on purpose:

https://mockbird.mockbird.workers.dev/m/demo/products?mock_status=500

Set the HTTP action's retry policy to None first so the failure is instant, run the flow, and your has failed branch β€” Teams alert, tracking-row update, whatever it does β€” actually executes, in the run history, where you can check its inputs. Remove the param and the same action returns 200. One URL parameter is the whole toggle, which makes it easy to keep a disabled "break glass" branch in the flow for drills. mock_status takes any code; combine with &mock_delay=2000 for slow-then-fail.

5. Timeouts and slow upstreams

curl -s -o /dev/null -w '%{time_total}\n' \
  'https://mockbird.mockbird.workers.dev/m/demo/products/1?mock_delay=3000'
# 3.79s

The HTTP action's Settings β†’ Timeout takes an ISO 8601 duration β€” set it to PT2S against a 3-second delay and the action times out on demand, so you can watch the has timed out run-after path fire and decide whether that should retry (Β§3) or alert (Β§4). mock_delay goes up to 5,000 ms; mock_jitter adds a random component if you want latency that isn't suspiciously constant.

6. Practice 429 handling before the real API rations you

# allow 3 requests per 60s per client, then 429 with Retry-After
'https://mockbird.mockbird.workers.dev/m/demo/products?mock_ratelimit=3&limit=1'
# 4 rapid requests β†’ 200 200 200 429

429 is on the retry policy's retryable list, so the default policy will grind through a burst β€” but a Do until loop hammering a rationed API deserves a rehearsal. Responses carry x-ratelimit-limit / x-ratelimit-remaining / x-ratelimit-reset, and the 429 includes a real Retry-After header β€” read it with outputs('HTTP')['headers']['Retry-After'] and feed it to a Delay action, which is the pattern the default policy can't give you.

7. See exactly what your flow sends

When a flow POSTs to a partner API and the partner says "malformed payload", the run history shows you Power Automate's rendering of the inputs β€” not always the wire truth (expression results, encoding, and headers can surprise you). Point the action at a bin instead:

curl -s -X POST https://mockbird.mockbird.workers.dev/m/demo/hooks/flow-run \
  -H 'content-type: application/json' -d '{"flow":"order-sync","runId":42}'
# β†’ {"ok":true,"caught":"POST /hooks/flow-run","body":{...},"receivedAt":"…"}

The demo's catch-all route echoes what it caught, and every hit β€” method, path, headers, body β€” lands in the public demo request inspector. On your own project, an empty project plus one ANY /* custom route is a private bin with a per-project inspector β€” webhook.site without the 7-day expiry.

8. Fire realistic deliveries at "When an HTTP request is received"

Mockbird projects can send outbound webhooks on every record change β€” signed POSTs with x-mockbird-event, x-mockbird-delivery, and x-mockbird-signature: sha256=… (HMAC-SHA256) headers. Aim them at the HTTP request trigger's URL (the long …logic.azure.com… URL the trigger generates when you save the flow):

# point your project's webhook at the flow's trigger URL (returns the signing secret)
curl -s -X PUT https://mockbird.mockbird.workers.dev/api/projects/YOUR_ID/webhook \
  -H "x-admin-key: YOUR_ADMIN_KEY" -H "content-type: application/json" \
  -d '{"url":"https://prod-27.westus.logic.azure.com/workflows/…/invoke?…sig=…"}'

# instant test delivery, no record edit needed:
curl -s -X POST https://mockbird.mockbird.workers.dev/api/projects/YOUR_ID/webhook/test \
  -H "x-admin-key: YOUR_ADMIN_KEY"

Now every record create/update/delete in the mock produces a realistic third-party delivery: your trigger's Parse JSON schema, the signature check you build with the returned secret in a Compose + Condition, and the flow's behavior under repeated deliveries all get exercised with real traffic instead of the "Run a test β†’ manually paste a payload" ritual. Delivery attempts (status, error, duration) are listed at GET …/webhook/deliveries. One honest constraint: deliveries travel the public internet β€” the trigger URL's SAS signature is its auth, so treat the stored URL like the secret it is. More recipes: sending test webhooks.

9. Your own API instead of the shared demo

One curl (or one click), no signup:

curl -s -X POST https://mockbird.mockbird.workers.dev/api/projects \
  -H "content-type: application/json" \
  -d '{"preset":"ecommerce"}'
# β†’ {"id":"abc123xyz9", "adminKey":"…", ...}

Presets: blog / ecommerce / saas β€” or define resources by hand, or import an OpenAPI spec, db.json, CSV, or HAR recording of the real API. Every simulation param above works on your project's URLs, and your project's openapi.json feeds Β§2's custom connector. Projects have a 10,000 requests/day cap β€” flow testing barely dents it.

Where static results are still the right tool

Fair's fair: for skipping an action that would touch real records (an approval, a Dataverse update) while you test everything downstream of it, static results are faster than any mock server β€” no URL to swap, and they work on connector actions that aren't HTTP at all. Use them for that (and remember to turn the beaker off before you ship β€” a known footgun). Reach for a hosted mock when the thing under test is the HTTP layer itself: retry policies, timeouts, 429s, run-after branches, payload encoding, or the custom-connector workflow. They compose β€” static-result the Dataverse write, mock the partner API.

Related: the Power BI / Power Query version of this guide, the Retool version, the Appsmith version, the Zapier version, the Make (Integromat) version, the n8n version, the Node-RED version, testing loading and error states, send test webhooks with real signatures, request bins compared, simulating rate limits, and mocking third-party APIs generally.

Verification: all demo curls on this page (seq 503β†’503β†’200β†’200, mock_status 500 and 404, 3.79s delay, 200 200 200 429 rate-limit run with retry-after present, bin echo + inspector log, openapi.json serving OpenAPI 3.0.3) were run against production on 20 Sep 2026 before publishing. Power Automate behavior β€” HTTP action/trigger and custom connectors being premium, retry policy defaults (exponential, 4 retries) and its 408/429/5xx scope, ISO 8601 timeouts, static results being preview and skipping execution, OpenAPI v3 import support β€” is from Microsoft's official docs and release notes; we don't run your tenant. If a step here doesn't work, that's a bug: tell us.