> For the complete documentation index, see [llms.txt](https://docs.does.qa/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.does.qa/platform/integrations/universal-webhook.md).

# Universal Webhook

Start a DoesQA Run from any system with an HTTP webhook.

The Universal Webhook is how almost any external system can start a DoesQA Run. Your pipeline, automation platform, or custom script sends an HTTP request. DoesQA selects Flows, starts the Run, and keeps going.

With this you can create an integration with any other service, or a script you own. One URL and key unlock Runs from GitHub, Bitbucket, Azure DevOps, Make, Zapier, n8n, and anything else that can send HTTP.

{% hint style="info" %}
This is the **inbound** hook that starts Runs. It is not the outbound notification webhook that posts results when a Run finishes. For outbound results, see [Notifications](/configuration/notifications.md).
{% endhint %}

## Why use it

* One URL and key work across CI tools and no-code platforms.
* You choose Flows with IDs, a [Run Recipe](/configuration/run-recipes.md), or tags.
* You can preview the selection with GET before you wire a pipeline.
* You can return immediately, or wait until the Run finishes.

Create and manage keys under **Settings → CI/CD**. Field-by-field detail for that screen lives on [CI / CD](/configuration/ci-cd.md).

## Before you call the hook

{% stepper %}
{% step %}

## Create a CI/CD key

In DoesQA, open **Settings → CI/CD**, create an **Active** key, and store the secret in your other system. DoesQA shows the secret once. See [CI / CD](/configuration/ci-cd.md).
{% endstep %}

{% step %}

## Copy your Account ID

Open **Settings** (Account Settings) and copy the **Account ID**. It is part of the hook URL.
{% endstep %}

{% step %}

## Decide how to select Flows

Pick one selection style per request. If more than one is present, DoesQA uses the first match in this order:

1. Flow IDs (`ids`)
2. A [Run Recipe](/configuration/run-recipes.md) (`recipe`)
3. Tags (`withAll` / `withoutAny`)
4. All Flows in the account

**Include tags** (`withAll`) mean the Flow must have every listed tag. **Exclude tags** (`withoutAny`) remove a Flow if it has any listed tag. Set Flow tags in [Flow settings](/platform/flow-builder.md#flow-settings).
{% endstep %}
{% endstepper %}

## Preview which Flows would run

Send a **GET**. Nothing starts.

```
GET https://app.does.qa/api/hook/ACCOUNT_ID?key=YOUR_KEY&withAll=smoke
```

Check the response count against the Flows you expect. Fix tags, recipe, or IDs before you add the call to CI or an automation.

## Start a Run

Send a **POST**:

```
POST https://app.does.qa/api/hook/ACCOUNT_ID?key=YOUR_KEY&withAll=smoke&label=Build%201234
```

By default the hook accepts the request and returns quickly once the Run is created (status `202`). To wait until the Run's Test Cases are created before your job continues, add `mode=wait` (status `200`). This waits for the Flow Runs and Test Cases to be recorded.

### Request options

| Parameter        | Required | What it does                                                                                                           |
| ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `key`            | Yes      | Your CI/CD webhook key. You can also send it as the `x-api-key` header.                                                |
| `label`          | No       | Label shown on the Run, such as a build number.                                                                        |
| `name`           | No       | Overrides the trigger name shown for the Run.                                                                          |
| `ids`            | No       | Comma-separated Flow IDs.                                                                                              |
| `recipe`         | No       | Run Recipe ID.                                                                                                         |
| `withAll`        | No       | Comma-separated include tags. The Flow must have all of them.                                                          |
| `withoutAny`     | No       | Comma-separated exclude tags. The Flow must have none of them.                                                         |
| `testsTagged`    | No       | Comma-separated tags. Only Test Cases that have all of them.                                                           |
| `testsNotTagged` | No       | Comma-separated tags. Excludes Test Cases that have any of them.                                                       |
| `values`         | No       | URL-encoded JSON object of Value overrides, or a JSON request body.                                                    |
| `mode`           | No       | `fast` (default) returns `202` once the Run is created. `wait` returns `200` once Test Cases are created and recorded. |

Authenticate with the query `key`, or with header `x-api-key: YOUR_KEY`.

Optional **Value** overrides replace matching items from the [Value Store](/values/value-store.md) for that Run. Pass them as the URL-encoded `values` query parameter or as a JSON request body with `POST`.

### Example with Value overrides

```
POST https://app.does.qa/api/hook/ACCOUNT_ID?key=YOUR_KEY&withAll=staging&label=PR-88&values=%7B%22BASE_URL%22%3A%22https%3A%2F%2Fstaging.example.com%22%7D
```

Decoded, `values` is:

```json
{
  "BASE_URL": "https://staging.example.com"
}
```

### Passing Values in the request body

For `POST` requests, send Values as a JSON body instead of URL-encoding them:

```bash
curl -X POST \
  "https://app.does.qa/api/hook/ACCOUNT_ID?key=YOUR_KEY&withAll=staging&label=PR-88" \
  -H "Content-Type: application/json" \
  -d '{"BASE_URL": "https://staging.example.com"}'
```

### Minimal curl example

```bash
curl -X POST \
  "https://app.does.qa/api/hook/ACCOUNT_ID?key=YOUR_KEY&withAll=smoke&label=manual-check"
```

## Response and error codes

| Code  | Response                        | What it means                                               |
| ----- | ------------------------------- | ----------------------------------------------------------- |
| `200` | JSON with Run ID and Test Cases | `mode=wait` succeeded. Test Cases are created and recorded. |
| `202` | JSON with Run ID                | `mode=fast` succeeded. The Run is created and continues.    |
| `401` | `{"code": "012"}`               | Invalid key. Check the key and that it is **Active**.       |
| `404` | `{"code": "022"}`               | Recipe not found. Check the `recipe` ID.                    |
| `503` | Maintenance message             | DoesQA is in maintenance. Retry after the window.           |

### Wait for Run results

`mode=wait` returns once the Run's Test Cases are created and recorded. For pass or fail results, use one of these options:

* The [GitHub Action](/platform/integrations/github.md) waits for results and fails the job when Tests fail.
* [Outbound notifications](/configuration/notifications.md) post results to Slack, Teams, email, or a webhook when the Run completes.

## Ready-made examples

| Tool         | Page                                                   |
| ------------ | ------------------------------------------------------ |
| GitHub       | [GitHub](/platform/integrations/github.md)             |
| GitLab       | [GitLab](/platform/integrations/gitlab.md)             |
| Bitbucket    | [Bitbucket](/platform/integrations/bitbucket.md)       |
| Azure DevOps | [Azure DevOps](/platform/integrations/azure-devops.md) |
| Make         | [Make](/platform/integrations/make.md)                 |
| Zapier       | [Zapier](/platform/integrations/zapier.md)             |
| n8n          | [n8n](/platform/integrations/n8n.md)                   |

Prefer a ready-made flow when one exists. Otherwise paste the [curl example](#minimal-curl-example) into the service or script you already use, and you are connected.

## After the Run starts

To post results to Slack, Teams, email, or an outbound webhook, create a notification rule and include the **CI/CD Webhook** run type. See [Notifications](/configuration/notifications.md).

## Related

* [Integrations](/platform/integrations.md)
* [CI / CD](/configuration/ci-cd.md)
* [Notifications](/configuration/notifications.md)
* [Run Recipes](/configuration/run-recipes.md)
* [Build smoke and regression coverage](/better-coverage/build-smoke-and-regression-coverage.md)
