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

# Webhooks & Artifacts

> Export task results automatically over webhooks or pull them via the API so findings flow into your own pipelines, ticketing, and storage.

When you run Neo through the API, you usually want the results flowing straight into your own systems: a security data lake, a ticketing system, a SIEM, or your own remediation pipeline. Instead of polling for status and copying results by hand, Neo can hand off a structured **completion artifact** the moment a task finishes.

There are two ways to receive that artifact:

| Delivery mode       | What Neo does on completion                                       | How you consume it                                             |
| :------------------ | :---------------------------------------------------------------- | :------------------------------------------------------------- |
| **Webhook (push)**  | POSTs the completion artifact to your configured team webhook URL | Your endpoint receives a `task.completed` payload in real time |
| **Artifact (pull)** | Persists the completion artifact for later retrieval              | You fetch it with `GET /api/v1/tasks/{id}/artifacts`           |

Both modes return the **same artifact payload**. You choose the mode per task with the `completion_delivery` parameter when you create the task. When you omit it, no completion handoff runs and results stay in Neo.

<Info>
  This capability is aimed at teams integrating Neo into external systems. It is configured through the API and team settings.
</Info>

## What's in the completion artifact

The completion artifact is a single structured snapshot of a finished task — everything a downstream system needs to act on the result without scraping the transcript. At a high level it captures:

* **Outcome** — the final task status and when the task completed.
* **Summary** — a human-readable description of what Neo did and what it concluded.
* **Findings** — the validated security issues Neo produced, plus a count.
* **References** — identifiers that tie the artifact back to the originating task and its output stream.

Both delivery modes return this same artifact. The full field-by-field schema is in [Webhook request](#webhook-request) below.

## Choosing a delivery mode

* **Use a webhook** when you want results pushed downstream automatically — opening tickets, posting to a queue, or triggering the next step in a pipeline without polling.
* **Use artifact (pull)** when your system would rather fetch results on its own schedule, or when you cannot expose an inbound endpoint for Neo to call.

## Push results to a webhook

### 1. Configure your team webhook

The webhook target is a **team-level setting**, so every webhook-mode task in the team is delivered to the same URL. Updating it requires a team admin.

Set the webhook URL with `PATCH /api/v1/teams`:

```bash theme={"system"}
curl -X PATCH https://neo.api.projectdiscovery.io/api/v1/teams \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "webhook_url": "https://hooks.example.com/neo/task-completed"
  }'
```

| Field         | Purpose                                                                                |
| :------------ | :------------------------------------------------------------------------------------- |
| `webhook_url` | HTTPS endpoint Neo POSTs the completion artifact to. Pass an empty string to clear it. |

### 2. Trigger a task with webhook delivery

Set `completion_delivery` to `webhook` when you create the task:

```bash theme={"system"}
curl -X POST https://neo.api.projectdiscovery.io/api/v1/tasks \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "task": "Run a security review of https://staging.example.com",
    "completion_delivery": "webhook"
  }'
```

When the task finishes, Neo POSTs the artifact to your team webhook URL.

### Webhook request

Neo sends a `POST` with a JSON body and these headers:

| Header                      | Value              |
| :-------------------------- | :----------------- |
| `Content-Type`              | `application/json` |
| `X-Neo-Event`               | `task.completed`   |
| `X-Neo-Completion-Delivery` | `webhook`          |

The body is the completion artifact, with an additional `event` field on webhook deliveries:

```json theme={"system"}
{
  "schema_version": 1,
  "event": "task.completed",
  "completion_delivery": "webhook",
  "task_id": "8c1a9f4e-2b6d-4f3a-9b2c-1e7d5a0c4f21",
  "stream_id": "01J9...",
  "status": "completed",
  "completed_at": "2026-06-25T17:42:11Z",
  "issue_count": 3,
  "summary": "Reviewed the staging environment and confirmed 3 issues...",
  "findings": [
    {
      "title": "Reflected XSS in search parameter",
      "severity": "high",
      "description": "...",
      "evidence": []
    }
  ]
}
```

| Field                 | Type              | Description                                                                                                                                                       |
| :-------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `schema_version`      | integer           | Payload schema version. Currently `1`.                                                                                                                            |
| `event`               | string            | `task.completed`. Present on webhook deliveries only.                                                                                                             |
| `completion_delivery` | string            | The delivery mode the task was created with (`webhook` or `artifact`).                                                                                            |
| `task_id`             | string (uuid)     | The task that produced the artifact.                                                                                                                              |
| `stream_id`           | string            | Identifier for the task's output stream, when available.                                                                                                          |
| `status`              | string            | Final task status, e.g. `completed`.                                                                                                                              |
| `completed_at`        | string (ISO 8601) | When the task finished.                                                                                                                                           |
| `issue_count`         | integer           | Number of findings in `findings`.                                                                                                                                 |
| `summary`             | string            | Human-readable summary of the task outcome.                                                                                                                       |
| `findings`            | array             | Structured issue objects with title, severity, description, evidence, and remediation. See the [API Reference](/api-reference/overview) for the full issue shape. |

## Pull results via the API

If you would rather fetch results yourself, create the task with `completion_delivery` set to `artifact`:

```bash theme={"system"}
curl -X POST https://neo.api.projectdiscovery.io/api/v1/tasks \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "task": "Run a security review of https://staging.example.com",
    "completion_delivery": "artifact"
  }'
```

Once the task completes, retrieve the persisted artifact:

```bash theme={"system"}
curl https://neo.api.projectdiscovery.io/api/v1/tasks/TASK_ID/artifacts \
  --header 'X-Api-Key: YOUR_API_KEY'
```

The response wraps the same artifact payload described above:

```json theme={"system"}
{
  "task_id": "8c1a9f4e-2b6d-4f3a-9b2c-1e7d5a0c4f21",
  "completion_delivery": "artifact",
  "artifact": {
    "schema_version": 1,
    "completion_delivery": "artifact",
    "task_id": "8c1a9f4e-2b6d-4f3a-9b2c-1e7d5a0c4f21",
    "status": "completed",
    "completed_at": "2026-06-25T17:42:11Z",
    "issue_count": 3,
    "summary": "...",
    "findings": []
  }
}
```

Pass `?refresh=true` to rebuild the artifact from the task's current issues if findings were updated after completion:

```bash theme={"system"}
curl "https://neo.api.projectdiscovery.io/api/v1/tasks/TASK_ID/artifacts?refresh=true" \
  --header 'X-Api-Key: YOUR_API_KEY'
```

## Delivery and security guarantees

* **Best-effort delivery.** Webhook delivery does not block or fail the task. If your endpoint is unreachable or returns a non-2xx status, the task still completes normally — so for guaranteed durability, treat the persisted artifact (`GET /api/v1/tasks/{id}/artifacts`) as the source of truth.
* **Timeout.** Neo waits up to 15 seconds for your endpoint to respond. Acknowledge quickly with a 2xx and process the payload asynchronously.
* **HTTPS only.** Webhook URLs must use `http` or `https`. Use HTTPS in production.
* **SSRF protection.** Neo will not call private or internal targets. URLs resolving to `localhost`, link-local, RFC 1918 private ranges, or cloud metadata endpoints are blocked.

## Use cases

| Use case                  | How Neo helps                                                                                                 |
| :------------------------ | :------------------------------------------------------------------------------------------------------------ |
| Ticketing automation      | Receive findings the moment a task completes and open issues in your tracker with full evidence and severity. |
| Pipeline orchestration    | Trigger downstream remediation, notification, or verification steps from the `task.completed` webhook.        |
| Storage and reporting     | Persist artifacts into your data lake or reporting store for historical analysis and audit trails.            |
| Polling-free integrations | Push results downstream automatically instead of repeatedly polling task status.                              |
| Pull-based ingestion      | Fetch artifacts on your own schedule when you cannot expose an inbound webhook endpoint.                      |
