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

# Send a test webhook

> Force a signed signal.test delivery to the Signal's webhook — no scrape, no credits.

**Cost: Free**

<Card title="How Signals work" icon="satellite-dish" href="/concepts/signals" type="tip" horizontal arrow="true" cta="Read the guide">
  Signals are scheduled change monitoring, billed per check. See what you can watch and how it's priced.
</Card>

Enqueues a signed `signal.test` event to the webhook resolved for this Signal (`notify.webhook_url`, else the account default). Does **not** scrape LinkedIn, charge credits, create a Trigger, or change the Signal snapshot.

Ideal for agent-driven integration tests: create a Signal → call this → poll [`GET /v1/webhook-deliveries/{delivery_id}`](/api-reference/webhooks/get-delivery).

<ParamField path="id" type="string" required />

<ParamField header="Idempotency-Key" type="string">
  Optional. Retries with the same key return the same `delivery_id` without enqueueing a duplicate.
</ParamField>

### Response

| Field         | Description                                    |
| ------------- | ---------------------------------------------- |
| `delivery_id` | Id to poll on `/v1/webhook-deliveries/{id}`    |
| `event`       | Always `signal.test`                           |
| `url`         | Destination URL (never the signing secret)     |
| `status`      | `retrying` (queued) \| `delivered` \| `failed` |

Returns `400 invalid_request` when no webhook URL is configured.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.up2data.ai/v1/signals/sig_9dk2m1xq/test-webhook \
    -H "X-API-Key: $UP2DATA_API_KEY" \
    -H "Idempotency-Key: agent-run-42"
  ```

  ```python Python theme={null}
  resp = requests.post(
      f"https://api.up2data.ai/v1/signals/{signal_id}/test-webhook",
      headers={
          "X-API-Key": UP2DATA_API_KEY,
          "Idempotency-Key": "agent-run-42",
      },
  )
  delivery_id = resp.json()["data"]["delivery_id"]
  ```

  ```ts TypeScript theme={null}
  const res = await fetch(
    `https://api.up2data.ai/v1/signals/${signalId}/test-webhook`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "Idempotency-Key": "agent-run-42",
      },
    },
  );
  const { data } = await res.json();
  // Poll GET /v1/webhook-deliveries/${data.delivery_id}
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "delivery_id": "wh_stest_a1b2c3d4e5f6g7h8",
      "event": "signal.test",
      "url": "https://app.example.com/hooks/up2data",
      "status": "retrying",
      "attempts": 0,
      "created_at": "2026-07-21T12:00:00.000Z"
    },
    "meta": {
      "creditsUsed": 0,
      "billed": false,
      "reason": "webhook_test_enqueued",
      "requestId": "req_whtest1"
    }
  }
  ```
</ResponseExample>

<Note>
  The payload includes `"test": true` and a fixture `diff` so receivers can branch away from production Triggers. Signature headers match production (`X-Up2Data-Event`, `X-Up2Data-Signature`).
</Note>
