The mental model
Reqloom models your API as a graph. Four ideas make up the whole thing; polling, assertions, retries, and hooks are detail layered on top.
| Idea | Answers |
|---|---|
| Actor | Who is making this request? |
| Resource | What thing does this endpoint act on? |
| Dependency | What must happen before it? |
| Variable | How does a value get from one response into the next request? |
1. Actors — who
Section titled “1. Actors — who”An actor is an identity your API recognises: admin, vendor, customer, a
worker service. You declare how to become it once.
name: admindescription: Marketplace admin (email + password)auth: strategy: simple method: POST path: /api/v1/auth/admin/login body: email: "{{env.admin_email}}" password: "{{env.admin_password}}" expect_status: 200 extract: token: $.data.accessToken admin_id: $.data.user.idsession: ttl: 15minject: headers: Authorization: "Bearer {{admin.token}}"Three parts: auth says how to log in and what to keep from the response,
session says how long to reuse it, inject says what every request as this
actor carries.
Any operation can then say actor: admin and get credentials automatically.
Anything the login extracted is available too — {{admin.admin_id}}, not just the
token. There are eleven auth strategies for the
different shapes real APIs use.
2. Resources — what
Section titled “2. Resources — what”A resource is a thing your API manages, grouping the operations that act on it.
name: orderdescription: Customer ordersoperations: create: method: POST path: /api/v1/orders actor: customer expect_status: 201 extract: order_id: $.data.id pay: method: POST path: /api/v1/orders/{{order.order_id}}/pay actor: customer depends_on: [order.create] expect_status: 200 extract: payment_id: $.data.payment.idThe resource id comes from name: — so this file gives you order.create and
order.pay, and the filename is irrelevant.
The resource owns the extracted values. create produced order_id, pay
produced payment_id, and both are now {{order.order_id}} and
{{order.payment_id}}. There is no {{order.create.order_id}} form. This is the
piece that makes everything else work.
3. Dependencies — what first
Section titled “3. Dependencies — what first”Two kinds of edge, and you need both:
Implicit — a reference. Writing {{order.order_id}} in pay’s path says
“whatever produces this must run first”. Most of your graph comes from this, free.
Explicit — depends_on, for a prerequisite that returns nothing you read but
must still happen:
add_item: method: POST path: /api/v1/cart/items actor: customer depends_on: [product.publish] # publish returns nothing we use, body: # but an unpublished product can't be bought product_id: "{{product.product_id}}" quantity: 2State changes — publish, activate, approve, verify — are the usual reason to reach
for depends_on.
From those edges the engine builds a chain, sorts it topologically with a deterministic tie-break, and runs it. Ask for a shallow endpoint and you get a shallow chain:
reqloom run product.list # chain of 1 stepsreqloom run cart.add_item # chain of 3 stepsreqloom run order.pay # chain of 5 stepsreqloom run refund.approve # chain of 7 stepsReqloom adds nothing when nothing is needed. product.list is a public listing
endpoint with no prerequisites, so it stays one request.
4. Variables — how values move
Section titled “4. Variables — how values move”One sigil, {{ ... }}. Six scopes:
path: /api/v1/orders/{{order.order_id}}/pay # a resource's extracted value headers: Authorization: "Bearer {{vendor.token}}" # an actor's session value Idempotency-Key: "{{$.uuid}}" # a builtin generator body: email: "{{env.customer_email}}" # an environment variable api_key: "{{secret.STRIPE_KEY}}" # an OS keychain secret first: "{{order[1].order_id}}" # a specific instance, 1-indexedResolution order is builtins → env → secret → actor sessions → indexed
resource → resource. An unresolved reference is left in place verbatim, so you see
braces in the URL rather than a silently empty segment.
Putting it together
Section titled “Putting it together”That’s the model. Running one endpoint:
- Parse the schema and validate every reference and
depends_ontarget - Build the graph, sort it, detect cycles
- For each step: authenticate the actor if its session has expired, substitute
{{...}}, send, extract into the resource, evaluate assertions - Report each step with a status and, on failure, an
E_*code
Running: refund.approve (chain of 7 steps, env=local) [1] Running: product.create (attempt 1) [2] Running: product.publish (attempt 1) [3] Running: cart.add_item (attempt 1) [4] Running: order.create (attempt 1) [5] Running: order.pay (attempt 1) [6] Running: refund.request (attempt 1) [7] Running: refund.approve (attempt 1)
Result: SUCCEEDEDThree actors took part in those seven steps. Their logins are not steps — a login belongs to whichever step needs it, and is cached for its TTL. Seven steps across three identities cost three logins.
What the model buys you
Section titled “What the model buys you”- Any endpoint, one command, however deep its prerequisites
- Auth declared once per identity instead of per request
- A schema that is also documentation — and reviewable in a pull request
- One schema, every environment — switch with
--env - A CI test runner with JUnit output and meaningful exit codes
What it isn’t
Section titled “What it isn’t”- A scripting platform. The schema is declarative; hooks are the escape hatch, not the model.
- A flow builder. The dependency graph is generated from the schema, not the other way round.
- GUI-first. The YAML is the source of truth; the desktop app is a view onto it.
- Actors — the eleven auth strategies and session behaviour
- Resources & operations — boundaries and extraction
- Dependency resolution — ordering, cycles, caching
- Variables & references — the full grammar
- Authoring guide — build one from scratch