# Tutorial: Your First API Test

{% hint style="info" %}
**Who is this for?** Developers and SDETs new to API testing in ContextQA. You will build one test case that authenticates against an API, chains the token into a second request, and validates the response.
{% endhint %}

API testing in ContextQA lets you send HTTP requests, assert response values, and chain data between calls — all from the same visual test editor you use for browser tests. Instead of writing scripts in Postman or pytest, you add REST API steps to a test case and let ContextQA handle execution, evidence capture, and failure analysis.

In this tutorial you will:

1. Create an API test case with a GET request
2. Add status code and payload validation
3. Store the response and chain it into a second request
4. Run the test and review per-step results

**End result:** A two-step API test that authenticates, captures a token, calls a protected endpoint with that token, and validates the returned data — with full execution evidence (request/response logs, timing, and pass/fail status per step).

## Prerequisites

* A ContextQA account with at least one workspace ([sign up](https://accounts.contextqa.com/onboard))
* A REST API you can test against (a public API or your own staging environment)
* The API's base URL, an authentication endpoint (if applicable), and at least one data endpoint
* Familiarity with [core concepts](/getting-started/core-concepts.md) — specifically test cases, steps, and variables

***

## Step 1: Create a test case with an API step

Start by creating a test case that sends a single GET request and confirms the API responds successfully.

1. In the left sidebar, click the **Test Development** icon.
2. Click the **+** button and select **Start recording**.
3. Enter a name for your test case: `API — User endpoint validation`.
4. In the step editor, type `rest` in the step search field and select **Rest API method** from the list.
5. Click the **three dots** icon on the step to open the API testing panel.

The panel displays fields for HTTP method, URL, headers, body, response storage, and validation.

6. Set the HTTP method to **GET**.
7. Enter your target endpoint URL. For example:

```
https://api.example.com/users/1
```

8. Click **Send** to execute the request interactively. The panel displays the response body, status code, and headers.

**Verify it worked:** The response panel shows a `200` status code and a JSON body containing user data. If you see a `401` or `403`, you need authentication — skip ahead to [Step 3](#step-3-chain-an-authenticated-request) to add an auth step first.

{% hint style="info" %}
**Tip:** Use the interactive **Send** button to preview responses before saving the step. This lets you inspect the JSON structure and plan your validation assertions before committing to a test step.
{% endhint %}

***

## Step 2: Add response validation

A test that sends a request without asserting the response passes even when the API returns wrong data. Add validation to catch regressions.

### Add a status code assertion

1. In the API testing panel, scroll to the **Validation** section.
2. Set the data type to **status**.
3. Set the comparator to **equal**.
4. Enter `200` as the expected value.

This assertion fails the step if the API returns any status other than `200`.

### Store the response for later use

1. In the **Store response** field, enter a variable name: `userResult`.
2. Click **Create** to save the step.

The full response — status code, headers, and body — is now stored in `userResult`. You can reference any field using dot notation: `userResult.body.email`, `userResult.body.name`, `userResult.headers.content-type`.

### Add a payload assertion

1. Click the **three dots** icon on the saved step to reopen the API testing panel.
2. In the **Validation** section, add a second assertion.
3. Enter a JSON path to a field you want to verify. For example, if the response contains an `email` field:

```
userResult.body.email
```

4. Set the data type to **string**, the comparator to **Equals**, and enter the expected value (for example, `user@example.com`).
5. Click **Create Update** to save.

**Verify it worked:** The step now shows two validation badges — one for status code, one for the payload field. Run the test case by clicking **Run** in the top toolbar. Open the execution results and confirm both assertions pass with green checkmarks.

> **Important:** If you are unsure of the exact JSON path, run the step once without payload validation. Open **Run History**, select the step, and navigate to the **Response Body** tab to see the full JSON structure. Use that structure to construct the correct path.

***

## Step 3: Chain an authenticated request

Most real APIs require authentication. In this step, you add an authentication call before the GET request and chain the resulting token into the second step's headers.

### Add an auth step

1. In the test case step list, click **Add Step** above your existing GET step so the auth step runs first.
2. Type `rest` and select **Rest API method**.
3. Open the API testing panel and configure the authentication request:

| Field           | Value                                                              |
| --------------- | ------------------------------------------------------------------ |
| **HTTP method** | POST                                                               |
| **URL**         | `https://api.example.com/auth/login` (your auth endpoint)          |
| **Headers**     | `Content-Type`: `application/json`                                 |
| **Body**        | `{"username": "testuser@example.com", "password": "TestPass123!"}` |

4. Under **Store response**, enter `authResult`.
5. In **Validation**, add a status code assertion: **status** equal `200`.
6. Click **Create** to save.

After this step runs, the access token is available at `authResult.body.access_token` (adjust the path to match your API's response structure).

### Inject the token into the GET step

1. Open the API testing panel on your existing GET step (step 2 in the test case).
2. In the **Headers** section, add a new header:

| Key             | Value                                    |
| --------------- | ---------------------------------------- |
| `Authorization` | `Bearer ${authResult.body.access_token}` |

3. Click **Create Update** to save.

At execution time, ContextQA resolves `${authResult.body.access_token}` using the live token from step 1. Because the token is captured fresh on every run, the test works even when tokens expire between sessions.

**Verify it worked:** Run the full test case. Both steps should pass:

| Step                      | Expected outcome                                                        |
| ------------------------- | ----------------------------------------------------------------------- |
| Step 1 (POST /auth/login) | Status `200`, token stored in `authResult`                              |
| Step 2 (GET /users/1)     | Status `200`, `Authorization` header resolved, payload assertion passes |

{% hint style="warning" %}
**Common mistake:** If step 2 fails with a `401` status, check that the `Authorization` header value exactly matches the path to the token in the auth response. Open **Run History** for step 1, navigate to the **Response Body** tab, and confirm the path — for example, some APIs return the token under `authResult.body.token` rather than `authResult.body.access_token`.
{% endhint %}

***

## Step 4: Run and review the results

With both steps configured, run the complete test case and review the evidence.

1. Click **Run** in the top toolbar.
2. Select an execution environment from the dialog and click **Run**.
3. The execution begins. Each API step shows a real-time pass/fail indicator as it completes.

When execution finishes, click **View Detailed Report**.

### What to check in the results

**Step-by-step breakdown** — each step shows:

* Pass/fail status for every validation assertion
* The full request sent (method, URL, headers, body)
* The full response received (status code, headers, body)
* Execution duration per step

**Response Body tab** — select any step to inspect the raw JSON response. Use this to:

* Confirm variable values were resolved correctly (check that `${authResult.body.access_token}` was replaced with an actual token in step 2's request headers)
* Copy JSON paths for additional assertions you want to add later
* Diagnose unexpected response structures

**Network log** — the **Network** tab shows every HTTP request made during execution, including timing and status codes. Use this to identify slow endpoints or unexpected redirects.

| Result                      | What it means                                                                                   |
| --------------------------- | ----------------------------------------------------------------------------------------------- |
| Both steps pass             | Authentication and data retrieval work correctly                                                |
| Step 1 fails (auth)         | Credentials are wrong, the auth endpoint changed, or the API is down                            |
| Step 1 passes, step 2 fails | The token is valid but the data endpoint has an issue — check the status code and response body |

***

## Summary

You built a complete API test in four steps:

1. **Created an API test case** with a GET request using the REST API step type
2. **Added validation** — a status code assertion and a payload assertion targeting a specific JSON field
3. **Chained an authentication call** by storing the auth response in a variable and injecting the token into the next step's headers
4. **Ran the test** and reviewed per-step results including request/response details and assertion outcomes

One test case now validates authentication and data retrieval in a single automated flow.

## Next steps

* **Add more assertions:** Validate additional response fields — check that `userResult.body.id` is a number, that `userResult.body.roles` contains the expected values, or that `userResult.headers.content-type` equals `application/json`.
* **Import from a Swagger specification:** If your API has an OpenAPI spec, import it to generate test cases for every endpoint and status code combination automatically. See [Creating API tests](/api-testing/creating-api-tests.md#generating-tests-from-a-swagger-or-openapi-specification).
* **Add structure validation:** Assert the full response shape to catch field additions or removals between deployments. See [Validating responses](/api-testing/validating-responses.md#structure-validation).
* **Build hybrid API + UI tests:** Chain an API response into a browser step — for example, create a user via the API and then verify the user appears in the UI. See [API chaining](/api-testing/api-chaining.md#hybrid-api--ui-chaining).
* **Run in CI/CD:** Add your API test to a test plan and trigger it from GitHub Actions or Jenkins on every pull request. See [GitHub Actions](/integrations/github-actions.md) or [Jenkins](/integrations/jenkins.md).

## Related pages

* [API Testing Overview](/api-testing/api-testing.md) — capabilities and concepts for API testing in ContextQA
* [Creating API tests](/api-testing/creating-api-tests.md) — all methods for creating API test cases, including Swagger import
* [Validating responses](/api-testing/validating-responses.md) — payload validation, structure validation, and header assertions
* [API chaining](/api-testing/api-chaining.md) — passing data between API calls and hybrid API + UI flows
* [Mock API testing](/api-testing/mock-api-testing.md) — recording and replaying API responses for stable tests
* [Running tests](/execution/running-tests.md) — execution options for test cases, suites, and plans

{% hint style="info" %}
**Test your API in minutes — no code required.** [**Start Free Trial →**](https://app.contextqa.com/register) — Or [**Book a Demo →**](https://contextqa.com/book-a-demo/) to see API testing with your endpoints.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learning.contextqa.com/api-testing/api-testing-tutorial.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
