> For the complete documentation index, see [llms.txt](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/integrations/data-integration.md).

# Data Integration

TWC provides two ways to load wishlist data into analytics platforms, data warehouses and other third-party systems:

* **REST APIs** let your system retrieve wishlist and Notify Me data on a schedule.
* **Webhooks** send wishlist events to your system as they occur.

You can use either method independently, or use webhooks for timely updates and the APIs for periodic reconciliation.

### Choose an integration method

| Method    | Best suited to                                  | Integration pattern                                                                |
| --------- | ----------------------------------------------- | ---------------------------------------------------------------------------------- |
| REST APIs | Scheduled imports, backfills and reconciliation | Your system requests records changed since its last successful import.             |
| Webhooks  | Near-real-time processing of wishlist activity  | TWC sends an event to your HTTPS endpoint when supported wishlist activity occurs. |

API access is provided by TWC.   Webhook credentials are generated separately by an authorised user in Store Console, as described below.

### Retrieve data using the REST APIs

Two endpoints support incremental data retrieval:

* [Get Notify Me Items](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/wishlist-rest-api/notify-me/getnotifymeitems) retrieves Notify Me records updated since a specified point in time.
* [Get All Wishlists Updated Since](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/wishlist-rest-api/wishlists/getallwishlistupdatedsince) retrieves wishlist data updated since a specified point in time.

The endpoint documentation describes the request parameters, authentication and response format.

For a reliable incremental import:

1. Store a checkpoint representing the last successfully completed import.
2. On the next run, supply that checkpoint as the `updatedSince` value.
3. Process the complete response before advancing the checkpoint.
4. Make your import idempotent so that processing the same record again does not create a duplicate.
5. Allow a small overlap between successive retrieval windows where practical. This protects against records changing near a checkpoint boundary; deduplicate overlapping results using their identifiers.

Use an earlier `updatedSince` value when a backfill or reconciliation is required.

### Receive data using webhooks

Webhooks send signed JSON payloads to a public HTTPS endpoint that you control.

#### Supported events

| Event type              | Sent when                           |
| ----------------------- | ----------------------------------- |
| `WISHLIST_CREATED`      | A wishlist is created.              |
| `WISHLIST_DELETED`      | A wishlist is deleted.              |
| `WISHLIST_ITEM_CREATED` | An item is added to a wishlist.     |
| `WISHLIST_ITEM_DELETED` | An item is removed from a wishlist. |

Notify Me data is retrieved through the [Get Notify Me Items](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/wishlist-rest-api/notify-me/getnotifymeitems) API; there is currently no corresponding Notify Me webhook in the supported event set.

#### Set up a webhook

**1. Generate webhook credentials**

In Store Console, open **Webhook Management**, find the **API Keys** card and select **Generate New Key** before attempting to register a webhook.

{% hint style="warning" %}
The **Register New Webhook** section appears above the **API Keys** card, but the credentials must be generated first. Registration will fail if no credentials have been generated.
{% endhint %}

Generating a key creates two credentials:

| Credential | Purpose                                                            |
| ---------- | ------------------------------------------------------------------ |
| API key    | Used during registration to validate your endpoint.                |
| Secret key | Used to sign webhook payloads with HMAC-SHA256. Store it securely. |

Copy and securely store the secret key as soon as it is displayed. It remains visible for approximately five minutes after generation and is not displayed again when the page is reloaded. If it is lost, you must generate a new secret and update your receiver; the previous secret will no longer verify new webhook deliveries.

**2. Create the receiving endpoint**

Your endpoint must:

* be publicly accessible over HTTPS;
* accept a validation `GET` request and return a `2xx` response;
* accept webhook `POST` requests containing JSON;
* preserve the raw request body for signature verification; and
* return a `2xx` response within five seconds after accepting an event.

During registration, TWC sends the API key in the following header:

```http
Authorization: Bearer <api-key>
```

Your endpoint should compare this value with the API key generated in Store Console before returning a successful validation response.

Webhook URLs cannot use HTTP, embedded URL credentials, redirects, or hosts that resolve to private, reserved, loopback or link-local IP addresses.

**3. Register events**

After generating the credentials, use **Register New Webhook** on the **Webhook Management** page:

1. Select one of the supported event types.
2. Enter the public HTTPS URL of your receiving endpoint.
3. Register the webhook.

During registration, TWC sends a validation `GET` request to the endpoint. Registration succeeds only if the endpoint validates the bearer API key and returns a `2xx` response.

One active endpoint can be registered for each event type in an environment. To change an endpoint URL, remove the existing subscription and register the event again using the new URL.

**4. Test the integration**

Trigger each registered event, then confirm that:

* your endpoint receives the expected payload;
* the signature is valid;
* the event is processed once even if it is delivered more than once; and
* your endpoint returns a timely `2xx` response.

### Webhook delivery

TWC sends each event as an HTTP `POST` with a JSON body. The `x-signature` header contains a lowercase hexadecimal HMAC-SHA256 signature calculated over the exact raw request body using your secret key.

Delivery has a five-second timeout and is retried up to five times when the endpoint times out, cannot be reached or returns a non-`2xx` response. Redirects are not followed. Webhook delivery is at least once, so your receiver must safely handle occasional duplicates.

Return `2xx` as soon as the event has been authenticated and accepted. Queue lengthy processing in your own system rather than completing it before responding.

#### Verify the signature

This Node.js example verifies a received webhook:

```javascript
const crypto = require('crypto');

function verifyTwcWebhook(rawBody, signatureHeader, secretKey) {
  const expected = crypto
    .createHmac('sha256', secretKey)
    .update(rawBody)
    .digest('hex');

  const expectedBuffer = Buffer.from(expected, 'utf8');
  const receivedBuffer = Buffer.from(signatureHeader || '', 'utf8');

  return expectedBuffer.length === receivedBuffer.length &&
    crypto.timingSafeEqual(expectedBuffer, receivedBuffer);
}
```

Verify the signature before parsing or acting on the payload. Use the raw bytes received from TWC rather than a re-serialised JSON object, as changes to spacing or key order will alter the signature.

### Webhook payloads

Every payload includes an `eventType`. A field can be `null` when no value is available.

#### Wishlist created or deleted

```json
{
  "eventType": "WISHLIST_CREATED",
  "id": "...",
  "customer_id": "...",
  "customer_ref": "...",
  "deleted": false,
  "description": "...",
  "email": "...",
  "name": "...",
  "wishlist_ref": "..."
}
```

#### Wishlist item created or deleted

```json
{
  "eventType": "WISHLIST_ITEM_CREATED",
  "id": "...",
  "deleted": false,
  "product_id": "...",
  "product_ref": "...",
  "purchased": false,
  "variant_product_id": "...",
  "variant_product_ref": "...",
  "wishlist_id": "...",
  "wishlist_item_ref": "..."
}
```

Fields ending in `_id` contain TWC identifiers. Fields ending in `_ref` contain the corresponding external platform identifiers, such as Shopify identifiers.

### Reliability recommendations

* Deduplicate webhook events using a stable combination such as `eventType` and `id`.
* Record processing failures and retry them within your own system after returning a successful response only if the event has been durably queued.
* Monitor endpoint availability and non-`2xx` responses.
* Keep the webhook secret outside source code and rotate it through TWC if it may have been exposed.
* Run a periodic API reconciliation when completeness is important. Webhooks provide timely event notification, while the APIs provide a practical recovery and backfill path.

Webhook subscriptions and credentials can be managed from the **Webhook Management** page in Store Console. Coordinate secret rotation with the team responsible for the receiving endpoint so it can be updated at the same time.
