> ## Documentation Index
> Fetch the complete documentation index at: https://control-dev.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscribe to Parquet webhooks

> Receive a signed event when consolidation completes and pull only changed data.

export const ControlAppLink = ({path, breadcrumb, children}) => {
  const link = <a href={`https://app.control.dev${path}`} target="_blank" rel="noopener noreferrer" aria-label={breadcrumb ? `Open ${breadcrumb} in Control` : undefined}>
      {children}
    </a>;
  return breadcrumb ? <Tooltip tip={breadcrumb}>{link}</Tooltip> : link;
};

Parquet webhooks notify your service that consolidation data changed. The webhook is a signal to query the Parquet API; it does not contain the exported data.

## Create a subscription

In Control, open the <Tooltip tip="Data outputs → Parquet → Overview"><ControlAppLink path="/data-outputs/parquet/overview"><strong>Parquet overview</strong></ControlAppLink></Tooltip>. Enter a public HTTPS callback URL and an optional signing secret.

The current event type is `dataform.consolidation.completed`. Callback URLs must:

* use absolute `https://` URLs;
* resolve to a public IP address;
* not contain embedded credentials;
* accept a `POST` within ten seconds.

Redirects are not followed. Control retries a failed delivery after approximately 1, 2, and 4 seconds.

## Request headers

| Header                      | Value                                                            |
| --------------------------- | ---------------------------------------------------------------- |
| `X-Control-Event`           | `dataform.consolidation.completed`                               |
| `X-Control-Event-Timestamp` | Unix timestamp                                                   |
| `X-Control-Signature`       | `t=<timestamp>,v1=<hex-hmac-sha256>` when a secret is configured |

## Example payload

```json theme={null}
{
  "id": "evt_123",
  "type": "dataform.consolidation.completed",
  "tenantId": "control",
  "occurredAt": "2026-04-13T09:00:00Z",
  "data": {
    "status": "Succeeded",
    "parquetApi": {
      "catalogPath": "/api/parquet-exports/catalog",
      "snapshotCreatePath": "/api/parquet-exports/snapshots",
      "historyPath": "/api/parquet-exports/history"
    }
  }
}
```

Additional invocation identifiers and requested tags can be present under `data`.

## Verify the signature

When a signing secret is configured, compute HMAC-SHA256 over:

```text theme={null}
<timestamp>.<raw request body>
```

Use the exact raw body bytes received by your server. Compare the lowercase hexadecimal digest with the `v1` value using a constant-time comparison. Also reject stale timestamps according to your own replay window.

## Recommended handler

1. Verify the timestamp and signature.
2. Deduplicate by event `id`.
3. Return a successful response quickly.
4. In background work, list or request the relevant snapshot.
5. Fetch the manifest and compare slice keys plus `contentHash` values.
6. Download and replace only changed accounting-month partitions.

The subscription list in Control shows the last attempt, last successful delivery, HTTP status, last error, and consecutive failure count.
