BLOG/DEVELOPER DAILY
THEME
DEVELOPER DAILY

API smoke tests in five lines

After every deploy, someone curls a few endpoints to make sure the service is alive. Turn that ritual into a loop of http + assert steps you can run from your terminal or from CI.

Jun 16, 2026 OrchStep Team 5 minROLE: Backend DeveloperSCALE: Any
RUNNABLE DEMO
Full source for this post: blog/api-smoke-tests
VIEW SOURCE

You ship the service. Then you open a terminal and curl the health endpoint, eyeball the status code, maybe hit /version to confirm the right build went out. It takes thirty seconds and you do it every deploy. It's a real test — it just lives in your muscle memory instead of a file.

The problem with muscle-memory tests is that they don't run in CI, they don't fail loudly, and the new person on the team doesn't know they exist. The first sign that /orders is 500ing is a customer, not a curl.

OrchStep has http and assert as first-class step functions. So the post-deploy ritual becomes a short, real workflow: GET each endpoint, assert the status, and let a loop cover the whole list.

One endpoint, two steps

The core is a GET that captures the status, then an assert that checks it:

name: api-smoke-tests
defaults:
  base: https://api.example.com
tasks:
  smoke:
    steps:
      - name: get-health
        func: http
        args:
          url: "{{ vars.base }}/healthz"
          method: GET
      - name: expect-200
        func: assert
        args:
          condition: '{{ eq steps.get-health.status_code 200 }}'
          message: "/healthz did not return 200"

That's the whole idea: http makes the request and exposes result.status_code (reachable from later steps as steps.get-health.status_code), and assert turns the expectation into a step that fails the run when it isn't met. No framework, no test harness — the same binary you use for everything else.

Cover the whole list with a loop

You rarely check one endpoint. Define the list once and loop:

orchstep.yml
name: api-smoke-tests
# Override at the CLI: --var base=https://staging.api.example.com
defaults:
  base: https://api.example.com
  endpoints:
    - /healthz
    - /version
    - /users
    - /orders

tasks:
  smoke:
    steps:
      - name: check
        func: shell
        do: echo "GET {{ vars.base }}{{ loop.item }} -> expect 200"
        loop:
          items: '{{ vars.endpoints }}'

The runnable demo echos each request so it works offline and in any environment. To make it hit the network, swap the shell step for the http + assert pair below — same loop, real requests:

      - name: check
        func: http
        args:
          url: "{{ vars.base }}{{ loop.item }}"
          method: GET
        loop:
          items: '{{ vars.endpoints }}'
      - name: assert-ok
        func: assert
        args:
          condition: '{{ lt steps.check.status_code 400 }}'
          message: "an endpoint returned a 4xx/5xx"

Run it

orchstep run smoke --var base=https://staging.api.example.com

Point it at staging, prod, or a preview environment with one --var. The run exits non-zero the moment an assert fails, which is exactly what you want from a smoke test.

Run it from CI

Because the binary refuses to hang waiting for input, the same task is safe to drop into a pipeline step right after deploy:

orchstep run smoke --var base=$DEPLOY_URL --output json

--output json gives your CI a machine-readable result; the exit code gates the pipeline. The thirty-second ritual is now a gate that runs on every deploy, for everyone.

What you actually gained

Concerncurl by handOrchStep
Status checkeyeball the outputassert step, fails the run
Many endpointsseveral curl linesone loop over a list
Target envedit the command--var base=...
Runs in CInoyes, exit code + --output json
New teammate finds itasks in Slackit's a task in the repo

If a one-line curl \|\| exit 1 already covers you, keep it. The moment you have more than one endpoint or want it in CI, the loop pays for itself.

Where to go next

Got a post-deploy curl ritual? Put the endpoints in a list and let the loop run it for everyone.

#API#TESTING#HTTP#CI
Try it in two minutes — one binary, no signup.
curl -fsSL https://orchstep.dev/install.sh | sh

RELATED — DEVELOPER DAILY