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

# Handle report completion

> Receive report events safely and make polling resilient.

Use job polling as the reliable baseline for every asynchronous report. Account-level report delivery can additionally send `report.completed` and `report.failed` events to an HTTPS destination configured in the AstroM8 dashboard.

## Verify the signature

Webhook deliveries include:

```http theme={null}
X-Astrom8-Timestamp: 1721808000
X-Astrom8-Signature: sha256=<hmac-sha256(secret, timestamp + "." + raw_body)>
```

Verify the signature against the exact raw request body before parsing it. Reject a timestamp outside your replay window, compare signatures in constant time, and return a `2xx` response only after accepting the event.

```ts theme={null}
import { createHmac, timingSafeEqual } from 'node:crypto'

const signed = `${timestamp}.${rawBody}`
const expected = `sha256=${createHmac('sha256', signingSecret).update(signed).digest('hex')}`
const valid = timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
```

## Delivery behavior

Deliveries are retried with backoff after transient failure. Your handler must be idempotent because an event may be delivered more than once. Store the event or job identifier before performing downstream work.

Webhook-management operations in the reference are customer-session authenticated. Configure destinations and review delivery history in the dashboard or through that session-authenticated API; never log the one-time signing secret.
