Skip to main content
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 modeWhat Neo does on completionHow you consume it
Webhook (push)POSTs the completion artifact to your configured team webhook URLYour endpoint receives a task.completed payload in real time
Artifact (pull)Persists the completion artifact for later retrievalYou 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.
This capability is aimed at teams integrating Neo into external systems. It is configured through the API and team settings.

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 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:
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"
  }'
FieldPurpose
webhook_urlHTTPS 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:
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:
HeaderValue
Content-Typeapplication/json
X-Neo-Eventtask.completed
X-Neo-Completion-Deliverywebhook
The body is the completion artifact, with an additional event field on webhook deliveries:
{
  "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": []
    }
  ]
}
FieldTypeDescription
schema_versionintegerPayload schema version. Currently 1.
eventstringtask.completed. Present on webhook deliveries only.
completion_deliverystringThe delivery mode the task was created with (webhook or artifact).
task_idstring (uuid)The task that produced the artifact.
stream_idstringIdentifier for the task’s output stream, when available.
statusstringFinal task status, e.g. completed.
completed_atstring (ISO 8601)When the task finished.
issue_countintegerNumber of findings in findings.
summarystringHuman-readable summary of the task outcome.
findingsarrayStructured issue objects with title, severity, description, evidence, and remediation. See the API Reference 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:
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:
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:
{
  "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:
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 caseHow Neo helps
Ticketing automationReceive findings the moment a task completes and open issues in your tracker with full evidence and severity.
Pipeline orchestrationTrigger downstream remediation, notification, or verification steps from the task.completed webhook.
Storage and reportingPersist artifacts into your data lake or reporting store for historical analysis and audit trails.
Polling-free integrationsPush results downstream automatically instead of repeatedly polling task status.
Pull-based ingestionFetch artifacts on your own schedule when you cannot expose an inbound webhook endpoint.