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

# Mirror Immoteur classified data to your database

> Build a filter-scoped local copy of Immoteur classified data with full exports, delta exports, and live webhooks

Use this guide to operate a local copy of the classified data selected by your Immoteur filters. It combines a full export for the first snapshot, live notifications for prompt updates, and delta exports to reconcile changes over time.

This is not an unfiltered copy of every Immoteur resource. It contains the public-exportable classifieds that currently match your configured service filters. The generated API reference remains the source of truth for payload schemas.

## Start the receiver before the baseline

Configure an HTTPS receiver and make it ready before requesting or scheduling the first export. If your receiver restricts source IPs, [allowlist Immoteur egress IPs before testing](./webhook#configure-the-endpoint).

```mermaid theme={null}
sequenceDiagram
  participant I as Immoteur
  participant R as Your receiver
  participant S as Local store
  R->>R: Receiver ready
  I->>R: Full export chunk
  R->>S: Upsert export items
  I->>R: Live classified notification
  R->>S: Persist event and snapshot
  R-->>I: 204 response
  I->>R: Later delta export
  R->>S: Reconcile changed snapshots
```

Keep the HTTP handler small: persist or enqueue the request, return `2xx`, then process it in your own worker. See [Webhook delivery, retries, and idempotency](./webhook-delivery) for the receiver, timeout, header, and retry contract.

## Establish the first snapshot with a full export

Choose a full `classifieds` export to establish the baseline. It sends every classified that currently matches your filters as one or more chunks, followed by an empty completion payload. Each item is a full public `Classified` snapshot.

```json theme={null}
{
  "exportId": "export identifier",
  "items": ["Classified snapshots"],
  "isComplete": false
}
```

This is the export payload shape, not a complete schema. Do not assume a fixed chunk size, delivery order, or number of deliveries. Treat `isComplete: true` with an empty `items` array as the terminal completion signal for that export.

## Process live classified notifications

Use the `classified` payload type for live notifications. They give your local copy prompt updates when a classified is created or when an eligible normalized field changes.

Persist a delivery ledger keyed by `X-Immoteur-Service-Id` and `X-Immoteur-Event-Id` before acknowledging a live notification. That event ID is stable across retries of a classified notification. `X-Immoteur-Delivery-Id` identifies an HTTP attempt only, so record it for diagnostics but do not use it as the idempotency key.

A `meta.lastSeenAt`-only revisit is recorded for export reconciliation and does not produce a direct live notification. Use `meta.lastModifiedAt` for normalized source changes and `meta.lastSeenAt` to retain the most recent observed revisit.

## Reconcile with delta exports

<Tabs>
  <Tab title="Full export">
    Use a full export for the first baseline and whenever you deliberately need
    a new snapshot of the current filter scope. It selects every currently
    matching public-exportable classified.
  </Tab>

  <Tab title="Delta export">
    Use configured delta exports after a successful compatible baseline. A delta
    selects ledger changes since that baseline, including changes that are
    useful for reconciliation but were not direct live notifications.
  </Tab>
</Tabs>

If no compatible successful baseline exists, the filter or destination changes, or the baseline is older than {/* immoteur-parameter:start {{immoteur.webhook.delta.baseline_max_age}} */}7 days{/* immoteur-parameter:end */}, a delta export falls back to a full export. Configure export days in the dashboard according to the reconciliation cadence your integration needs.

## Make local writes safe for duplicates and late delivery

Store each source snapshot by classified identifier, retain the raw payload, and keep your own enrichment in separate fields or tables. Do not let arrival order, chunk position, delivery ID, or retry count decide which source snapshot wins.

When applying a snapshot, prefer the newer `meta.lastModifiedAt`. When the modified timestamp is equal, you may retain the later `meta.lastSeenAt` without overwriting newer normalized data. `status.current` is a lifecycle field; do not infer deletion solely because an item is absent from a later export. A changed filter creates a new selection scope and is not an automatic instruction to remove records from your database.

## Use the local copy for analysis and enrichment

Once source snapshots are stored, run your own analysis, joins, scoring, CRM sync, or enrichment against your database. Keep those derived values separate from the Immoteur snapshot so an incoming source update remains a straightforward upsert rather than a conflict with your local work.

## Questions developers ask

### Does this mirror all Immoteur data?

No. It mirrors the public-exportable classified data that currently matches the filters configured for your service. Use the API reference and your service configuration to understand the exact payload and selection.

### Can I rely on arrival order or receive each event once?

No. Webhook deliveries can be retried and exports can use several chunks. Persist an idempotency ledger for live notifications and upsert snapshots by classified identifier.

### When should I choose full or delta?

Start with a full export. Keep live notifications running for prompt updates, then use delta exports for regular reconciliation. A delta automatically falls back to a full export when there is no compatible recent baseline.

### Should I delete a local record missing from a later export?

Not automatically. An export reflects its current filter scope. Keep lifecycle decisions explicit and use the classified snapshot, including `status.current`, instead of treating absence as a deletion command.
