Actors
An actor is an identity your API recognises — an admin, a vendor, a customer, a worker service. You describe how to become that identity once, and every operation that runs as it gets credentials automatically.
That’s the difference between Reqloom and an HTTP client. In Postman you paste a token into a variable and refresh it by hand when it expires. Here, the login is part of the schema and the engine runs it when it’s needed.
What an actor holds
Section titled “What an actor holds”name: vendordescription: Marketplace vendor with email/password auth
auth: # how to become this identity strategy: simple method: POST path: /api/v1/auth/vendor/login body: email: "{{env.vendor_email}}" password: "{{env.vendor_password}}" expect_status: 200 extract: token: $.data.accessToken refresh_token: $.data.refreshToken vendor_id: $.data.user.id
session: # how long credentials stay valid ttl: 15m
inject: # what to attach to every request headers: Authorization: "Bearer {{vendor.token}}"Three parts, and each answers a separate question:
auth— what request(s) produce a session, and what to pull out of the responsesession— how long to reuse it before authenticating againinject— what every operation running as this actor should carry
Using an actor
Section titled “Using an actor”Name it on the operation:
name: productoperations: create: method: POST path: /api/v1/vendors/{{vendor.vendor_id}}/products actor: vendor expect_status: 201 extract: product_id: $.data.idTwo things happened there. actor: vendor means the Authorization header from
inject is attached. And {{vendor.vendor_id}} uses a value the login response
produced — extractions aren’t limited to tokens. Anything the auth response
returns is available as {{<actor>.<name>}} anywhere in the schema.
Omit actor: for a public endpoint. No auth is attached and no login runs:
list: method: GET path: /api/v1/productsWhy actors are worth the trouble
Section titled “Why actors are worth the trouble”Because a real workflow crosses identities. Approving a refund in the sample project touches three:
Running: refund.approve (chain of 7 steps, env=local) [1] Running: product.create (vendor) [2] Running: product.publish (vendor) [3] Running: cart.add_item (customer) [4] Running: order.create (customer) [5] Running: order.pay (customer) [6] Running: refund.request (customer) [7] Running: refund.approve (admin)Three logins happen as part of that run, and none of them appear as chain steps — a login is part of the step that needs it. You never asked for them, and you never copied a token.
Supported auth strategies
Section titled “Supported auth strategies”The simple strategy above is one login request. Real APIs vary, so there are
eleven, set with auth.strategy:
| Strategy | Use when | Network call |
|---|---|---|
simple | One login request returns a token | yes |
chain | Login takes several steps — OTP, MFA, tenant select | yes |
basic | HTTP Basic | no |
api_key | A static key in a header, query param, or cookie | no |
bearer | You already hold the token | no |
oauth2_client_credentials | Machine-to-machine OAuth 2 | yes |
oauth2_password | OAuth 2 resource-owner password grant | yes |
oauth1 | OAuth 1.0a, HMAC-SHA1 signed per request | no |
aws_sigv4 | AWS Signature v4 | no |
jwt | You sign your own JWT | no |
mtls | Client-certificate TLS | no |
strategy defaults to simple.
Several need no request at all, because the credential already exists:
name: servicedescription: CI service account using a long-lived tokenauth: strategy: bearer token: "{{secret.SERVICE_TOKEN}}"session: ttl: 24hMulti-step logins use chain, where each step can use what the previous extracted:
name: customerauth: strategy: chain steps: - id: request_otp method: POST path: /api/v1/auth/otp/request body: phone: "{{env.test_phone}}" expect_status: 200 - id: verify_otp method: POST path: /api/v1/auth/otp/verify body: phone: "{{env.test_phone}}" code: "{{env.test_otp}}" expect_status: 200 extract: token: $.data.accessToken customer_id: $.data.user.idinject: headers: Authorization: "Bearer {{customer.token}}"See auth strategies for the exact keys each one reads.
One actor per identity, not per credential
Section titled “One actor per identity, not per credential”The useful boundary is who the API thinks you are, not which token you hold.
Same credential, different acting identity — like Stripe’s Stripe-Account
header — is still two actors, because the API treats them differently:
name: platformauth: strategy: bearer token: "{{secret.STRIPE_KEY}}"inject: headers: Authorization: "Bearer {{platform.token}}"name: connectedauth: strategy: bearer token: "{{secret.STRIPE_KEY}}"inject: headers: Authorization: "Bearer {{connected.token}}" Stripe-Account: "{{env.connected_account_id}}"Conversely, don’t create admin_readonly and admin_write if the API issues them
the same identity — that’s one actor, and the difference belongs in the request.
Sessions are cached
Section titled “Sessions are cached”An actor authenticates once per session lifetime, not once per operation. Seven steps as one customer means one login. See sessions & caching for TTL, refresh, and expiry.
Where credentials should live
Section titled “Where credentials should live”Never in the schema. Environment variables hold the non-sensitive half and
!secret binds the rest to your OS keychain:
name: localvariables: vendor_email: vendor@marketplace.test vendor_password: !secret VENDOR_PASSWORDThe schema stays committable. See secrets.
- Auth strategies — all eleven, with exact keys
- Sessions & caching — TTL and refresh
- Resources & operations — what actors act on