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

# Trigger runs from your CI

> Start a Peeps test run from any CI system, deploy pipeline or script with one authenticated HTTP request to an incoming webhook.

An incoming webhook is a URL that starts a test run when your system calls it. Use one to run tests from your own CI, a deploy pipeline, a hardware test rig or a script.

Each incoming webhook belongs to a project. It decides which tests run and in which environment. The request only says "run now".

## Create an incoming webhook

You need the Contributor role or above.

<Steps>
  <Step title="Open incoming webhooks">
    In Peeps, open **Settings** and select **Incoming webhooks** under **Triggers**.
  </Step>

  <Step title="Create it">
    Click **Create incoming webhook** (**Create your first incoming webhook** if the project has none). If you see tabs, choose **Manual setup**. **GitHub (one-click)** is only for GitHub deployments.
  </Step>

  <Step title="Choose what runs">
    Give it a **Name**. Then pick the tests to run: one or more **Selections**, one or more **Test cases**, or both. Only test cases with a published script are listed.
  </Step>

  <Step title="Choose where it runs">
    Set **Test run environment**. Every run this webhook starts uses that environment and its variables, including `BASE_URL`. If the environment is missing a variable the chosen tests use, Peeps asks you to add it before you can create the webhook.
  </Step>

  <Step title="Save the secret">
    Click **Create incoming webhook**. Peeps shows the webhook URL and its secret. **Save the secret now**: Peeps shows it only once.
  </Step>
</Steps>

**Environment (optional)** and **Branch (optional)** are filters on the request, not settings for the run. Leave them empty to run on every call. See [Filters](#filters).

## Call it

Send a `POST` to the webhook URL with the secret in the `X-Peeps-Secret` header:

```bash theme={null}
curl -X POST "https://app.peepsai.com/api/v1/incoming-webhooks/<webhook-id>" \
  -H "Content-Type: application/json" \
  -H "X-Peeps-Secret: $PEEPS_WEBHOOK_SECRET" \
  -d '{"event": "pull_request"}'
```

Keep the secret in your CI system's secret store, never in the repository.

### Request body

The body is optional JSON. Peeps reads these fields:

| Field | What it does |
| - | - |
| `event` | A label for this call, shown in the webhook's activity log. It doesn't change what runs. |
| `environment` | Checked against the webhook's environment filter. It doesn't choose the environment the tests run in. |
| `ref` | The branch, as `main` or `refs/heads/main`, checked against the webhook's branch filter. If you send a 40-character commit SHA here instead, Peeps skips repeat calls to this webhook for that commit for the next 10 minutes. |
| `release` | The release this run's batch belongs to, up to 80 characters. Leave it out to use the project's current release, or send `null` for none. |

Peeps treats a body that isn't valid JSON as empty. Other fields Peeps reads come from GitHub deploy events, and you don't need them.

### Response

A `200` means Peeps accepted the call. The body says what happened:

```json theme={null}
{
  "status": "success",
  "runsQueued": 2,
  "runs": [{ "runId": "…" }, { "runId": "…" }]
}
```

`"status": "filtered"` means nothing ran. If a filter skipped the call, the `reason` field says which one. If Peeps couldn't start the tests, for example because one has no published script, the `error` field says why.

If the webhook's selections hold no tests, the call succeeds with `"runsQueued": 0`.

| Code | Meaning |
| - | - |
| `200` | Accepted. Check `status` for `success` or `filtered`. |
| `400` | The `release` is invalid: not text, over 80 characters, or holding characters other than letters, digits, spaces and `. _ + - ( )`. |
| `401` | The secret is missing or wrong. |
| `403` | The webhook is turned off. |
| `404` | No webhook has this ID. |
| `413` | The body is over 1 MB. |
| `429` | Too many calls. Wait the number of seconds in the `Retry-After` header. |
| `500`, `503` | Peeps couldn't take the call. Try again. |

Each webhook accepts up to 10 calls a minute. Every call counts toward the limit, including calls a filter skips and calls with a wrong secret.

## Filters

Filters let one webhook ignore some calls. A call that a filter skips returns `200` with `"status": "filtered"`.

* **Environment (optional).** Runs only when the request's `environment` matches. A call with no `environment` still runs.
* **Branch (optional).** Runs only when the request's `ref` names this branch. A call with no `ref` still runs.

To run the same tests against two environments, create one webhook for each.

## Check what happened

Open the webhook from **Incoming webhooks** to see its activity log. Each accepted call shows whether it ran tests, was skipped and why, or failed, with the runs it started. Calls with a wrong secret, calls to a turned-off webhook and calls to an unknown ID aren't logged, so check the response code for those.

To replace the secret, click **Regenerate** on the webhook's page, or **Regenerate secret** in its menu in the list. The old secret stops working immediately.

## What a call can't do yet

A call can't change the tests' target URL or pass values into the run. Every run uses the webhook's test run environment exactly as it is set in Peeps. If each run needs a different target, such as a device assigned for one pull request, contact [support@peepsai.com](mailto:support@peepsai.com).

## Next

To have Peeps call your system back when the tests finish, see [Call your system when tests finish](/automation/call-back-when-done).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.