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

# Event Export

> Inspect and export your request, webhook, and stream delivery event history as JSON or NDJSON with filters, outside the live API response path.

You need a support-friendly way to inspect request, webhook, and stream event history outside the live API response path. SEC API supports filtered delivery-ledger listing and JSON or NDJSON exports backed by Postgres, which is the source of truth for delivery history.

## Endpoints

* `GET /v1/delivery/events`
* `GET /v1/delivery/events/export`

Use the `/v1/delivery/events` namespace for delivery history so it does not collide with SEC event APIs such as enforcement, auditor-change, and voting-result routes.

## Filtered event inspection

```bash theme={null}
curl "$SECAPI_BASE_URL/v1/delivery/events?kind=event&type=artifact.created&requestId=req_123&limit=20" \
  -H "x-api-key: $SECAPI_API_KEY"
```

Useful filters:

* `kind`
* `type`
* `requestId`
* `since`
* `limit`

## Export JSON

```bash theme={null}
curl "$SECAPI_BASE_URL/v1/delivery/events/export?kind=event&limit=100&format=json" \
  -H "x-api-key: $SECAPI_API_KEY"
```

## Export NDJSON

```bash theme={null}
curl "$SECAPI_BASE_URL/v1/delivery/events/export?kind=webhook_delivery&since=2026-03-14T00:00:00Z&format=ndjson" \
  -H "x-api-key: $SECAPI_API_KEY"
```

Use NDJSON when downstream tooling wants line-oriented ingestion into log processors or ad hoc support scripts.

## CLI

```bash theme={null}
secapi events list --kind event --request-id req_123 --limit 20
secapi events export --kind webhook_delivery --since 2026-03-14T00:00:00Z --format ndjson
```

## Job-completion webhooks (no polling)

Async jobs announce their terminal state as webhook events, so you no longer have to poll:

* `intelligence.query.completed` / `intelligence.query.failed` — an async `/v1/intelligence/query` job finished.
* `export.completed` / `export.failed` — an async bulk export finished and a signed download URL is available.

Subscribe by adding the type to a webhook endpoint's `subscribedEventTypes` (see webhook-stream-workflows). Sample `export.completed` payload:

```json theme={null}
{ "jobId": "exp_…", "status": "completed", "dataset": "company_overview", "format": "csv", "rowCount": 50, "downloadUrl": "https://…signed…", "expiresAt": "2026-06-30T00:15:00Z" }
```

### Verifying webhook signatures

Outbound webhooks are signed exactly like Stripe: an HMAC-SHA256 over `${timestamp}.${rawBody}` using your endpoint's signing secret, delivered in the signature header. Recompute the HMAC over the raw request body and compare in constant time before trusting a payload.

## Bulk export → signed URL

For datasets too large to inline in a tool result, materialize them once to a short-lived signed download URL.

* MCP tool `exports.create` — e.g. `{ "dataset": "company_overview", "tickers": ["AAPL","MSFT",…], "format": "csv", "idempotency_key": "portfolio-A" }` returns an `export_job` with the `downloadUrl` (valid \~15 min) directly in the response, and also emits `export.completed` (for webhook subscribers / audit). Reusing the same `idempotency_key` returns the same file instead of regenerating. Bills per entity, like `companies.overview`.
* MCP tool `exports.get` — re-sign the URL later with `{ "jobId": "exp_…", "format": "csv" }`. Returns not-found for an unknown or expired job.

## Operational notes

* exports are tenant-scoped
* request correlation is driven by `Request-Id`
* support should prefer exports over direct database access for tenant-scoped delivery history
* stream polling uses per-subscription delivery records, so re-reading the same cursor window does not create new billable delivery units
* when Postgres is configured and the durable ledger cannot be read, the API returns `delivery_ledger_unavailable` with HTTP 503 rather than returning an empty history
