Quick Start: API Access
Generate a Stairwell auth token and make your first authenticated REST request, with the responses to expect and what each failure means.
Two things stand between you and a working Stairwell API call: a token, and knowing which URL to send it to. This page does both. By the end you will have generated an auth token, looked a file up by its hash, and run a filtered query, which is enough to tell whether a real integration is worth building and enough to debug it when it breaks.
Everything here uses curl, so it works from any machine with a shell. If a command line tool would serve you better than a client you maintain, stop after step 1 and read swell instead: it uses the same token.
What do I need before I start?
- A Stairwell account with access to at least one environment.
- Permission to generate an auth token for your organization. If Auth tokens is not in your settings, someone with a higher role has to generate one for you.
curl, andjqif you want readable output.
You do not need swell, an installed forwarder, or any prior setup.
How do I create an auth token?
- Sign in at app.stairwell.com.
- Open Settings from the left menu.
- Select Auth tokens under the Organization section.
- Click Generate Token and choose the API/CLI token type.
- Name it after what will use it, not after you.
nightly-ioc-sweepis a name that tells the next person whether revoking it breaks something;mike-token-2is not. - Click Generate and copy the token now. It is shown once and cannot be retrieved afterwards.
Put it somewhere your automation reads from and your shell history does not:
export STAIRWELL_TOKEN="paste-it-here"The token carries your own access. Anything you can see in the app, it can see through the API, and nothing you cannot. That is worth saying plainly because it means a token in the wrong place is exactly as serious as your password being in the wrong place.
How do I find my environment ID?
In Settings, open the Environments tab and select the environment. Its ID is on the detail page.
You will need it for anything scoped to a fleet: assets, YARA rules, threat reports, groups, triggers. File lookups do not take one.
If you already have swell, this is faster:
$ swell foundation getenvsThat prints one row per environment you are authorized to reach, with its ID.
How do I make my first request?
Look a file up by hash. It is a read, it changes nothing, and it exercises the token, the network, and your authorization at once.
curl -s -H "Authorization: Bearer $STAIRWELL_TOKEN" \
"https://app.stairwell.com/v1/objects/<sha256>/metadata" | jq .Substitute a hash you have. Any hash Stairwell holds will do, including one from a threat report you have imported. You can pass an MD5 or a SHA-1 instead of a SHA-256: the lookup accepts any of the three and the response always identifies the file by its SHA-256, which is the canonical name to store.
What comes back is the file's identity and what Stairwell knows about it: the three hashes, the size, when Stairwell first saw it anywhere, which of your environments it has been seen in, the YARA rules it matched, its tags, and its verdict under malEval. An empty malEval means analysis has not finished, not that the file is clean. See Verdicts for reading it.
How do I run a query instead of a lookup?
The list endpoint takes a filter written in Stairwell's query language, the same language as the search bar in the app:
curl -s -H "Authorization: Bearer $STAIRWELL_TOKEN" \
--get "https://app.stairwell.com/v1/objects/metadata" \
--data-urlencode 'filter=object.first_seen_time >= "now-1d"' \
--data-urlencode 'pageSize=10' | jq '.objects[].sha256'Two things about that call are load-bearing.
pageSize caps at 50. It also defaults to 50. Anything that walks a large result set is a loop: take nextPageToken from the response and pass it back as pageToken until it comes back empty. Write that loop before you need it, because the request that returns exactly 50 results looks like a complete answer.
With no environment named in the filter, the query covers every environment you can read. That is usually what you want and occasionally a surprise. Add object.environment_id == "YOUR_ENVIRONMENT_ID" to pin it.
CEL Query Language is the field-by-field reference for what you can put in that filter.
How do I know it worked?
A 200 with a JSON body whose name field is objects/<sha256>/metadata. If jq prints an object rather than an error, you are authenticated and authorized and the rest is ordinary API work.
What if it does not work?
The status code tells you which of the three things went wrong.
401or403. The token. Either it was not sent (check the header spelledAuthorization: Bearer <token>, with the space), it was revoked, or you pasted it with a trailing newline. Generate a fresh one before you debug anything else.404on a hash you are sure exists. Stairwell holds no object with that hash in an environment you can read. Confirm the hash in the app first. A file another team holds in an environment you cannot read is a404to you, and that is authorization working rather than a missing file.400on the list endpoint. The filter. Paste it into the search bar in the app, which reports syntax errors in a way a REST response cannot. Quoting is the usual culprit: the filter's own double quotes have to survive your shell.- A TLS or certificate error. Something between you and Stairwell is intercepting the connection. Do not reach for a flag that skips verification. Run the checks on Pre-Deployment Check, which explains what the failure means and who fixes it.
- A hang or a timeout. Egress. The API is on
app.stairwell.comover port 443, and a network that allows the web app usually allows this too, so a timeout here points at a proxy rather than a firewall.
What should I read next?
- REST APIs, for which of Stairwell's surfaces to use for what, and where each reference lives.
- CEL Query Language, for writing filters that return what you meant.
- MCP Server, for asking questions of the same data in natural language.
- swell, if the job is better done by a tool than by a client you have to maintain.
Updated 20 days ago