> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurtest.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Spur is an AI-powered QA engineer that lets teams create and run automated end-to-end tests for web and mobile apps using natural language.
> When answering questions about Spur, cite the relevant page from docs.spurtest.com.

# Make an API Call

> Add an API Call step in Spur to hit a backend HTTP endpoint for state setup, response assertions, or extracting values like auth tokens for reuse in later steps

## Overview

The **Make an API Call** step lets a test hit a backend HTTP endpoint directly, without
going through the UI. Use it to:

* **Set up state** before the UI test runs (create a user, seed data, reset an account)
* **Assert** on a backend response (status code, returned data)
* **Extract a value** — such as an auth token — and reuse it in later steps

It works in both **web** and **mobile** tests.

## How to access

1. Type `/` in an empty test step to open the shortcuts menu
2. Select **Make an API Call**
3. Fill in the request using the structured editor (you don't write the request by hand)

## Request fields

| Field                  | Description                                                                                                                                                                                                                  |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Method**             | `GET` or `POST`                                                                                                                                                                                                              |
| **URL**                | The endpoint to call. Supports `{{variables}}`.                                                                                                                                                                              |
| **Headers**            | Add request headers. Choose an **environment header/secret** (resolved automatically by name at run time) or type a **hardcoded** header. Values support `{{variables}}`.                                                    |
| **Query Params**       | Key/value pairs appended to the URL. Values support `{{variables}}`.                                                                                                                                                         |
| **Body**               | Request body for `POST`, entered as JSON.                                                                                                                                                                                    |
| **Expect Status**      | The status code(s) that count as success — a single code or a comma-separated list. Defaults to `200, 201, 202, 204`. The step **fails** if the response status isn't in this set.                                           |
| **Save Response To**   | A variable name to store the response in, so later steps can reference it.                                                                                                                                                   |
| **Keep full response** | Optional checkbox under **Save Response To**. Skips the default truncation so the entire response body is kept in memory. Use this when a later step (for example, a JavaScript extractor) needs to parse the whole payload. |

## Using variables and secrets

* **Template variables** — reference values from earlier steps (e.g. extractions, scenario
  data, a saved response) anywhere that supports `{{variables}}`: the URL, header values,
  query params, and body.
* **Environment headers & secrets** — pick a header from your environment in the Headers
  picker and it's **resolved automatically by name** at run time (you don't need a
  `{{...}}` template for it). This keeps secrets like API keys out of the test definition.
* **Reading fields from a saved response** — when you **Save Response To** a variable, you
  can reach into the JSON with a dotted path, including array indices:
  `{{loginResponse.token}}`, `{{loginResponse.user.id}}`, `{{searchResults.items.0.name}}`.

## Examples

**GET and save a token, then reuse it**

```text theme={null}
Make an API Call
  Method: POST
  URL: https://api.example.com/auth/login
  Body: { "email": "qa@example.com", "password": "{{password}}" }
  Expect Status: 200
  Save Response To: loginResponse
```

A later API Call can then send the token from the saved response:

```text theme={null}
Make an API Call
  Method: GET
  URL: https://api.example.com/me
  Headers: Authorization = Bearer {{loginResponse.token}}
  Expect Status: 200
```

**Set up state before the UI test**

```text theme={null}
Make an API Call
  Method: POST
  URL: https://api.example.com/test/reset-account
  Headers: X-Api-Key  (environment secret — resolved automatically)
  Expect Status: 200, 204
```

## Working with JavaScript steps

A response you **Save Response To** is also available to
[JavaScript steps](/authoring-tests/test-side-peek/step-types/javascript) as `window.env.<name>` — holding the **raw
response text**. This lets you parse a payload, pull out the value you actually need,
and save *that* for later steps. It's the standard way to extract something buried in a
JSON response — an email's id, a token, or an item from a list.

The pattern is three steps:

**1. API Call — fetch and save the payload**

```text theme={null}
Make an API Call
  Method: GET
  URL: https://api.example.com/inbox
  Expect Status: 200
  Save Response To: inboxData
```

**2. JavaScript — parse it, operate on it, and `return` the value**

Read `window.env.inboxData`, run your logic, and `return` the result. Use `save:` to
store the returned value under a name:

`save:emailMsgId`

```javascript theme={null}
const inbox = JSON.parse(window.env.inboxData);
const m = (inbox.messages || [])
    .filter(x => (x.subject || '').toLowerCase().includes('account activation'))
    .sort((a, b) => b.time - a.time)[0];
if (!m) throw new Error('No matching email');
return m.id;
```

Return value (stored as `emailMsgId`):

```text theme={null}
"jzkrokxcnttvn16-1781018899-09738591515"
```

**3. Use it downstream** — reference `{{emailMsgId}}` in any later step (a UI step, or
another API Call):

```text theme={null}
Make an API Call
  Method: GET
  URL: https://api.example.com/messages/{{emailMsgId}}
  Expect Status: 200
```

<Note>
  `window.env.<name>` is the **raw response text**, so `JSON.parse()` it before reading
  fields. Throwing inside the script (`throw new Error(...)`) fails the step — handy as an
  assertion when the expected data isn't present.
</Note>

<Tip>
  If you only need a simple field — not custom logic — you can skip JavaScript and read it
  directly with a dotted template, e.g. `{{inboxData.messages.0.id}}`. Reach for a
  JavaScript step when you need filtering, sorting, or conditional logic (like picking the
  newest "account activation" email above).
</Tip>

## Notes

<Note>
  Only `GET` and `POST` are supported.
</Note>

<Tip>
  Set **Expect Status** to assert the backend behaved correctly — e.g. `200` for a
  successful login, or `401` when you're deliberately testing a rejected request. A
  response outside the expected set fails the step.
</Tip>

<Warning>
  Large responses are truncated when saved, so reference the specific field you need
  (e.g. `{{loginResponse.token}}`) rather than relying on the full body downstream.
  Enable **Keep full response** if a later step needs the entire body — for example, a
  JavaScript step that parses a long email body or a large JSON payload.
</Warning>

<Tip>
  Press `Cmd+Enter` (macOS) or `Ctrl+Enter` (Windows/Linux) inside an API Call editor
  to save the step and collapse it — the same shortcut used elsewhere in Spur.
</Tip>
