Restless Tutorial
Open the app

Restless tutorial

Restless is an API tester that runs in your browser. Build a request, send it, inspect the response, and add tests that check it automatically. This page walks through every feature, in roughly the order you'll need them.

Everything is stored in this browser until you sign in. Signing in is optional; it adds sync, share links, mock servers and monitors.

1. Your first request

  1. In the sidebar, open the Examples collection and click Get Lipsum.
  2. Answer the small sum next to Send (for example seven + 3 = → type 10 or ten).
  3. Click Send or press Ctrl/⌘ + Enter.
  4. The response appears below: the status (200 OK), the time and size, then the body. The Tests tab shows 5/5: the example comes with tests that check the response.

To test your own API, click + in the tab bar for a new request, type a URL such as https://api.example.com/users, and send. If you leave out https://, it's added for you.

2. The math check

Every Send (and every WebSocket/SSE Connect) needs the sum next to the Send button answered. It keeps bots from using the site's proxy. The numbers are 0–10, with plus or minus, and some numbers are written as words. Answer in digits or words.

  • A new question appears after each send. Press ↻ for a different one.
  • A correct answer is good for 10 minutes of background requests: the collection runner, OAuth token fetches and GraphQL schema loads. A long run only asks once.
  • If you see "Answer the math check next to Send first", fill in the box and try again.

3. Finding your way around

Counters on the editor tabs (for example Headers (2), Tests (3)) show what's filled in at a glance.

4. Request tabs

  • New tab: the + at the end of the tab bar, or Alt + T.
  • Close: the × on a tab, middle-click it, or Ctrl/⌘ + Shift + W.
  • A ● on a tab means it was opened from a collection and has unsaved changes. The note next to the request name says the same.
  • Clicking a saved request that's already open switches to its tab instead of opening a copy.
  • Tabs and their contents survive reloads. Responses don't; send again after reloading.

5. Method, URL and params

  • Pick the method on the left: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, or Realtime WebSocket/SSE.
  • Params and the URL stay in sync. Type ?page=2 in the URL and a row appears; add a row and the URL updates. Untick a row to drop it without deleting it.
  • Paste a cURL command into the URL box and the whole request is filled in: method, URL, headers, body and basic auth.
  • Name the request in the title above the URL. That name is used when you save it.

6. Headers

Add a header in the empty row at the bottom of the list; a new empty row appears as you type. Untick to disable, × to remove. Values can use variables, e.g. X-Request-Id: {{$uuid}}.

You don't need to set Content-Type for JSON, XML, form, multipart or GraphQL bodies; it's added for you. A header you set yourself always wins.

7. Authorization

Choose a type in the Auth tab. Every field accepts {{variables}}, so keep real secrets in secret variables (see Variables).

TypeWhat it sendsNotes
Bearer tokenAuthorization: Bearer <token>Most JWT/OAuth APIs.
Basic authAuthorization: Basic …Username and password, base64-encoded for you.
API keyA header (e.g. X-API-Key) or a query paramChoose Add to: Header or Query param.
OAuth 2.0Authorization: Bearer <access token>See below.
Digest authAnswers the server's Digest challengeNeeds Send through the proxy on.
AWS Signature v4Signed Authorization, X-Amz-DateAccess key, secret, optional session token, region and service (e.g. execute-api, s3).

OAuth 2.0

  • Client credentials: fill in the token URL, client ID, secret and scope. The token is fetched automatically when you send and refreshed when it expires. Get new access token fetches one now.
  • Authorization code (+PKCE): also fill in the authorization URL, then click Get new access token. A login popup opens. Register this redirect URI with your provider: https://restlessapp.dev/oauth/callback.html (the exact one is shown in the Auth tab).
  • The token status shows when it expires and whether there's a refresh token. Clear token forgets it.

8. Request bodies

Body typeUse it for
JSONMost APIs. Format pretty-prints it. Variables work inside, e.g. {"id": "{{userId}}"}.
XML / Raw textSOAP, XML APIs, plain text.
Form (urlencoded)Classic HTML form posts: key/value rows.
Multipart (files)File uploads. Each row is Text or File; choose a file with Choose file.
Binary fileSend one file as the raw body (images, PDFs, zips).
GraphQLQuery + variables, with a schema explorer. See GraphQL.

Files are kept in this browser only. They aren't synced, shared or exported, so after importing on another device you'll need to choose them again.

9. GraphQL

  1. Set the method to POST, enter the GraphQL endpoint, and choose body type GraphQL.
  2. Click Load schema. The explorer lists the queries and mutations the API offers.
  3. Click a field to insert a ready-made query (with its arguments as variables), then adjust it.
  4. Put variables as JSON in the Variables box, e.g. {"code": "DE"}.

Try it with https://countries.trevorblades.com/graphql.

10. Variables and environments

Write {{name}} anywhere: URL, params, headers, auth, body, test values. Click Variables in the top bar to manage them.

  • Environments are sets of values, such as Local, Staging and Production, each with its own baseUrl and keys. Switch with the Environment dropdown in the top bar.
  • Globals apply in every environment. The active environment overrides a global with the same name.
  • Secret variables 🔒: click the lock on a row. The value is masked, and it is never synced, shared, exported or sent to monitors unless you say so. Put passwords and keys here.

Built-in variables

{{$uuid}}A random UUID
{{$timestamp}}Unix time in seconds
{{$isoTimestamp}}e.g. 2026-11-08T03:34:25.716Z
{{$randomInt}}A random integer 0–999
{{$randomEmail}}A random test email address
{{origin}}This site's address (for its own /api/echo and mocks)

If a request says Unknown variable {{name}}, it isn't defined in the active environment or Globals.

11. Tests

Tests run after every send, in the collection runner and in monitors. Add them in the Tests tab with + Add test, pick a check and fill in its fields. Results appear in the response's Tests tab (e.g. Tests 4/5).

CheckExample
Status code equals / is one of / is 2xx200 · 200,201
Response time below (ms)500
Header exists / containscontent-type contains json
Body contains text / matches regex"ok":true · id":\s*\d+
JSON path exists / equals / containsdata.user.email equals [email protected]
JSON path is typeitems is array (string, number, boolean, object, array, null)
JSON array/string length equalsitems length 3

JSON paths

Use dots and indexes: data.items[0].id. Use [*] to collect every match: data.items[*].id gives [1, 2, 3], which you can compare with equals [1,2,3].

A test with a required field left blank fails with "fill in the expected value" rather than passing by accident.

12. Chaining requests

Chaining saves a value from one response as a variable, so later requests can use it. Typical example: log in, keep the token, call the API with it.

Try the built-in chain

  1. Send Examples → Get a todo. Its Extract tab saves the response's title as {{todoTitle}}.
  2. Open Create a post. Its body uses "title": "{{todoTitle}}".
  3. Send it. The title from step 1 is filled in, and its test confirms it came back.

Make your own

  1. On the first request, open Extract → + Add extraction.
  2. Name the variable (e.g. token), choose a source and where to find it, and a scope.
  3. Send it. The response's Tests tab lists each extracted value.
  4. Use {{token}} in the next request: in a header, in Auth → Bearer token, in the URL…
SourceFind it with
JSON pathdata.access_token, items[0].id
HeaderLocation, X-Request-Id
Set-CookieThe cookie name, e.g. session
Body regex (group 1)token=(\w+)
Status code(no path needed)

Scope: Environment saves into the active environment (or Globals if none is active); Globals saves for every environment. To run a whole chain in order, put the requests in a collection and use the runner.

13. Scripts

For logic that the Tests and Extract tabs can't express, use JavaScript in the Scripts tab. The pre-request script runs before sending and can change the request; the test script runs after the response. Use the snippet menus above each editor for ready-made examples.

// Pre-request: compute values, edit the request
rl.variables.set("ts", Date.now());
rl.request.headers.upsert({ key: "X-Trace", value: rl.variables.get("ts") });

// Test script: assertions and saving values
rl.test("status is 200", () => rl.expect(rl.response.code).toBe(200));
const body = rl.response.json();
rl.test("has users", () => rl.expect(body.users.length).toBeGreaterThan(0));
rl.environment.set("firstUserId", body.users[0].id);
console.log("saved", body.users[0].id);
APIWhat it does
rl.environment, rl.globals.get(k), .set(k, v), .unset(k) on the active environment / globals
rl.variablesValues for this request or run only
rl.iterationDataThe current row of a runner data file
rl.requestmethod, url, headers.get/add/upsert/remove, body.raw
rl.responsecode, status, responseTime, headers.get(), json(), text()
rl.test(name, fn)A named test; it fails if fn throws
rl.expect(x)Jest-style: toBe, toEqual, toContain, toBeGreaterThan…
pm.*Postman-style: pm.test, pm.expect(x).to.equal(…), pm.response.to.have.status(200)

Scripts run in a locked-down sandbox: no network, no page or cookie access, 5-second limit. Output from console.log appears in the response's Console tab.

14. Request settings

Send through the proxyOn (default): the site's server sends the request, so CORS never blocks it and you get full timing and raw details. Off: your browser sends it directly. Needed for localhost and private-network APIs, which the proxy refuses.
Follow redirectsOff shows the 3xx response and its Location instead of following it.
Use the cookie jarSend and store cookies automatically (see Cookie jar).
Verify TLS certificatesTurn off for self-signed or expired certificates (testing only).
Proxy endpointSend from another region you've set up (see App settings).
TimeoutMilliseconds; 0 uses the default (25 s).

15. Reading the response

  • Body: Pretty (formatted, coloured JSON/XML), Raw, or Preview for HTML pages (scripts disabled), images, PDFs, audio and video.
  • JSON filter: type a path such as data.items[*].name above the body to show only that part.
  • Headers and Cookies: cookies the response set, plus what's in the jar for this URL.
  • Tests: pass/fail for each test and script test, and the values that were extracted.
  • Console: output from your scripts.
  • Raw: the exact HTTP request and response text, with copy buttons. Useful for bug reports.
  • The toolbar has Copy body, Save example and HAR (download the exchange for browser dev tools or other tools).

16. Timing and certificates

The Timing tab breaks the request down into phases:

DNS lookupTCP connectTLS handshake SendWaiting (server time, TTFB)Download
  • A long Waiting bar means the server is slow; long DNS/TCP/TLS means connection setup.
  • The history sparkline shows how this request's time has changed over your last sends (min, average, p95, max).
  • Connection shows the IP address, HTTP version, TLS version and cipher, and the server region that measured it.
  • TLS certificate shows who issued it, its expiry and days remaining, the names it covers and the chain.

Through the proxy, phases are measured from the server to the API. In direct mode the browser measures them, and some details are hidden by the browser.

17. Examples and comparing responses

  • Save example stores the current response with the saved request (name it, e.g. 200 OK or 404 missing).
  • The Compare tab shows a line-by-line diff against the previous response or any saved example. Tick Include status & headers to compare those too. Handy for spotting what changed after a deploy.
  • Saved examples also become the responses of a mock server.

18. WebSocket and Server-Sent Events

  1. Choose WebSocket or SSE in the method menu (Realtime group).
  2. Enter the URL (e.g. wss://echo.websocket.org), answer the math check and click Connect.
  3. The log shows messages as they arrive (↓), what you sent (↑) and connection events. JSON is formatted.
  4. For WebSocket, type in the message box and press Send (or Ctrl/⌘ + Enter). Click Disconnect when done.

Realtime connections go directly from your browser, so the server must allow it. Monitors skip realtime requests.

19. Collections and history

  • Save (Ctrl/⌘ + S): the first time, choose a collection or folder, or create a new collection. After that, saving updates it in place.
  • + New collection in the sidebar. A collection's ⋯ menu has: new request, new folder, rename, share link, publish as mock server, create monitor, export and delete; ▶ runs it. A request's ⋯ menu has: open in new tab, duplicate, rename, share and delete.
  • Folders can be nested. Drag and drop requests and folders to reorder them or move them between folders and collections.
  • Search (top of the sidebar) filters collections and history by name, method or URL.
  • History keeps your last 100 sends. Click one to open it again.
  • Deleting shows an Undo button for a few seconds.

20. Collection runner

Click ▶ on a collection (or Run folder in a folder's menu) to send every request in order and check all the tests.

  • Iterations repeats the whole run. Delay waits between requests (for rate-limited APIs).
  • Data file (CSV or JSON): one iteration per row; each column becomes a variable. For example a CSV with email,password columns lets the requests use {{email}} and {{password}}.
  • Stop on first failure ends the run at the first failed request.
  • Values extracted by one request are available to the next, so chains work.
  • Afterwards, export a report: JUnit XML (for CI systems), HTML (to share) or HAR.
# users.csv
email,role
[email protected],admin
[email protected],viewer

21. Cookie jar

When a response sets cookies, they're stored and sent automatically to later requests for the same site, like a browser would (domain, path, expiry and Secure rules apply). This makes login-then-call flows work without copying cookies. Open Cookies in the top bar to see, add or delete them; turn the jar off per request in Settings.

22. Import, export and code

  • Import (top bar): paste text or choose a file. Restless recognises:
    • cURL commands (opened as a new tab)
    • Postman collections and environments (v2.0 and v2.1)
    • OpenAPI 3 and Swagger 2 specs, JSON or YAML: one request per operation, grouped by tag, with {{baseUrl}}
    • HAR files from browser dev tools
    • Restless exports
  • Export saves everything to a JSON file for backup or moving to another browser. Secret values are left out. Export a single collection from its ⋯ menu.
  • Code (next to Save) turns the current request into a snippet: cURL, JavaScript fetch, axios, Node.js, Python requests, Go, PHP, HTTPie or PowerShell. Variables are filled in.

23. Account and sync

  • Click Sign in → Create an account (email and a password of 8+ characters).
  • Your collections, environments and globals then sync automatically to your account and to any other browser where you sign in. The top bar shows ✓ Synced, ● Unsynced or an error.
  • Secret variable values stay on each device; you enter them once per browser.
  • If two devices change things at the same time, you're asked which version to keep.
  • The account menu has sync on/off, Sync now, change password, sign out and delete account (removes everything stored for it).

24. Share links

  1. Choose Share in a request's ⋯ menu (or the Share button above the URL), or Share link in a collection's menu.
  2. Optionally tick Also create an edit link, then Create link.
  3. Send the view link to anyone; opening it imports the request or collection into their Restless.
  4. People with the edit link can push changes back (Push changes to share); everyone can Pull latest from share. Keep edit links private.

Secret variables and OAuth tokens aren't included, but headers and auth fields typed directly into a request are. Use secret variables for credentials. Manage or delete your links in the sidebar's Cloud tab.

25. Mock servers

A mock server answers with your saved examples, so front-end work and demos can go ahead before the real API exists.

  1. Send requests in a collection and click Save example on the responses you want.
  2. In the collection's ⋯ menu choose Publish as mock server.
  3. You get a URL like https://restlessapp.dev/mock/AbC123xyz. Click Create environment with baseUrl to point your requests at it.
  • Routes come from the requests' URLs. {{baseUrl}} is dropped and {{id}} becomes a wildcard, so /users/42 matches /users/{{id}}.
  • If a route has several examples, add ?status=404 to pick one.
  • Publishing again updates the same URL. Mock servers are public, so don't save secrets in examples.

26. Monitors

A monitor runs a collection on a schedule from the server, even when your browser is closed, and alerts you when it starts failing and when it recovers.

  1. In a collection's ⋯ menu, choose Create monitor.
  2. Choose a schedule (every 5, 15 or 30 min, 1, 6 or 12 hours, or daily) and the environment to use.
  3. Add a webhook URL (Slack or Discord incoming webhook, or any URL) and/or an email for alerts.
  4. Open it from the Cloud tab to see run history (green/red dots), details of each run, Run now, edit and delete.

Monitors use a snapshot of the collection. Choose Edit → Update the snapshot after changing the requests. They run tests and extractions, not scripts, and can't reach private or localhost addresses.

27. App settings and regions

  • Theme: the ◐ button switches light and dark; Settings → Theme also offers System.
  • Proxy endpoints: to measure from another part of the world, deploy a second copy of this site in another Netlify region and add it under Settings → Proxy endpoints. Then pick it per request in Settings → Proxy endpoint. The Timing tab shows which region answered.
  • Echo endpoint: {{origin}}/api/echo returns what it received. Add ?status=404 or ?delay=2000 to test error and timeout handling.

28. Keyboard shortcuts

Ctrl/⌘ + EnterSend (press again to cancel)
Enter in the URL or math boxSend
Ctrl/⌘ + SSave
Alt + TNew tab
Ctrl/⌘ + Shift + WClose tab
Ctrl/⌘ + LSelect the URL
Tab in body and script editorsIndent

29. Troubleshooting

"Answer the math check next to Send first"
Type the answer to the sum next to Send. In the runner, answer the copy shown in the runner window.
"Requests to private or reserved addresses are blocked"
The proxy won't call localhost or internal networks. Turn off Send through the proxy in Settings to call them from your browser.
"The browser blocked or failed the request" (direct mode)
Usually CORS: the API doesn't allow browser calls. Turn Send through the proxy back on.
"Unknown variable {{name}}"
Define it under Variables, check the right environment is selected, or send the request that extracts it first.
Digest auth doesn't work
Digest needs the proxy. Turn on Send through the proxy.
"Upstream request timed out"
The API took longer than the timeout. Raise it in Settings (up to 25 s).
A file says "re-select: file not stored"
Files live in one browser only. Choose the file again.
The app looks broken after an update
Your browser may be using old files. Reload with Ctrl/⌘ + Shift + R.

Open the app Back to top