# Ingest

Public ingest is how you turn an external event into a Hooksbase delivery. You send a request to one webhook-specific ingest URL, authenticate with that webhook's ingest secret, and Hooksbase persists the source payload before the delivery coordinator takes over.

## Auth model

- **Endpoint** `public webhook URL`: Ingest requests go to `POST /v1/ingest/{publicId}`.
- **Credential** `whsec_...`: Authenticate with `Authorization: Bearer whsec_...`.
- **CLI / SDK**: The TypeScript SDK exposes `client.ingest.publishJson()`, `publishBytes()`, and webhook-name variants (`publishJsonByWebhookName()`, `publishBytesByWebhookName()`). The CLI exposes `hooksbase ingest send`.

## Public ingest contract

Ingest accepts the raw request body and records it as the source payload for the delivery. Ingest is served on `hooks.hooksbase.com` (not `api.hooksbase.com`). JSON is not required unless the webhook has a saved payload transform or a provider verifier that expects JSON.

Body size is capped at 10 MB; larger requests return `413`.

**Publish one JSON event**

```bash
curl https://hooks.hooksbase.com/v1/ingest/hook_123 \
  -H "Authorization: Bearer whsec_..." \
  -H "content-type: application/json" \
  -H "Idempotency-Key: order_123" \
  -d '{
    "type": "order.created",
    "orderId": "ord_123"
  }'
```

Success returns:

- `deliveryId`
- `sequenceNo`
- `status` of `queued` or `scheduled`

Duplicate idempotent calls return `duplicate: true` and the existing delivery reference instead of creating a second delivery.

## Scheduling and idempotency

Use the `x-hooksbase-deliver-at` header to request a future delivery time as a Unix timestamp in **milliseconds** (the SDK exposes this as the `deliverAt` option).

Scheduling rules:

- the explicit header overrides the webhook default delay
- per-request future delivery with `x-hooksbase-deliver-at` and webhook-level default delivery delay require Pro+ support
- recurring cron schedules are managed through `/v1/webhooks/{id}/schedules` and require Starter+
- `strict_fifo` webhooks reject future scheduling
- if the effective delivery time is in the past, Hooksbase accepts it immediately

Idempotency matters because it makes retries safe:

- send an `Idempotency-Key` whenever you might retry
- duplicate ingest does not consume storage or backlog twice
- duplicate repair can restore a missing sequence number when the first request persisted but coordinator handoff was interrupted

## Routing, transforms, and quotas

Before a delivery is persisted, Hooksbase evaluates:

- webhook and project lifecycle state
- routing against the original source payload and headers
- payload transforms when configured
- ingest-rate, backlog, and stored-payload quota admission

Important behavior:

- routing always sees the original payload, not the transformed outbound body
- transform-enabled ingest requires JSON input and JSON output
- paused destination routing failures return `400` before persistence
- paused webhook ingest returns `409`
- archived or missing webhook ingest returns `404`
- disabled project ingest returns `409`

## Common mistakes

- Forgetting the `Authorization: Bearer whsec_...` header.
- Publishing JSON-looking data with the wrong content type and then enabling a transform.
- Assuming a changed route rule or transform will affect existing deliveries or replays.
- Scheduling into the future on a webhook configured for `strict_fifo`.
