> For the complete documentation index, see [llms.txt](https://docs.chord.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chord.co/collect-data/everyone-else/server-events.md).

# Server events

Server events are sent from your backend straight to Chord when something happens to an order: it's placed, cancelled, refunded or shipped. They don't depend on the shopper's browser, so ad blockers and closed tabs can't stop them, and they're the reliable record of what was sold.

Your backend sends each event as an HTTP request to Chord's events endpoint. This page walks through it.

## Step 1: Get your endpoint and write key

Ask Chord for:

* **Your CDP domain**, such as `https://production.cdp.ingest.chord.co`.
* **A server-side write key.** It's different from the write key your storefront uses. Keep it secret: store it with your other backend credentials, never in browser code.

Server events go to these endpoints on your CDP domain:

* **Track** (something happened): `/api/track`
* **Identify** (who a customer is): `/api/identify`

## Step 2: Send events when they happen

Send a track event from your backend each time one of these happens. Each event's page in the tracking plan lists its properties.

* An order is placed: [Order Completed](/collect-data/tracking-plan/order-completed.md)
* An order is cancelled: [Order Cancelled](/collect-data/tracking-plan/order-cancelled.md)
* An order is refunded: [Order Refunded](/collect-data/tracking-plan/order-refunded.md)
* An order ships: [Shipment Shipped](/collect-data/tracking-plan/shipment-shipped.md)
* An order is delivered: [Shipment Delivered](/collect-data/tracking-plan/shipment-delivered.md)
* A customer creates an account: [User Created](/collect-data/tracking-plan/user-created.md)

If you sell subscriptions, send the subscription events in the tracking plan too, such as [Subscription Created](/collect-data/tracking-plan/subscription-created.md) and [Subscription Payment Failed](/collect-data/tracking-plan/subscription-payment-failed.md).

Every track request carries:

* **`type`** (required): `track`
* **`event`** (required): the event name, such as `Order Completed`
* **`properties`**: the event's properties from the tracking plan
* **`userId`**: your ID for the customer, if they have an account
* **`anonymousId`**: the browser's anonymous ID (see step 3)

Send your write key in the `X-Write-Key` header. Here's a complete Order Completed request:

```shell
export CHORD_CDP_DOMAIN="https://production.cdp.ingest.chord.co"
export CHORD_WRITE_KEY="your-server-side-write-key"

curl -X POST "$CHORD_CDP_DOMAIN/api/track" \
  -H "Content-Type: application/json" \
  -H "X-Write-Key: $CHORD_WRITE_KEY" \
  -d '{
    "type": "track",
    "event": "Order Completed",
    "userId": "customer-8812",
    "anonymousId": "a1b2c3d4e5",
    "properties": {
      "order_id": "100045",
      "order_date": "2026-11-04T11:45:45-05:00",
      "currency": "USD",
      "revenue": 89.99,
      "shipping": 5.00,
      "tax": 5.00,
      "total": 99.99,
      "email": "customer@example.com",
      "products": [
        {
          "product_id": "PRD-17",
          "sku": "PRD-17-BLU-M",
          "name": "Linen shirt",
          "price": 89.99,
          "quantity": 1,
          "revenue": 89.99
        }
      ]
    }
  }'
```

Chord adds `timestamp`, `receivedAt` and `messageId` to each event. Send your own `timestamp` if the event happened earlier than you're sending it, for example when you replay a queue.

{% hint style="info" %}
If your system can't set headers, you can send the write key as a `writekey` query parameter (all lowercase) or a `writeKey` property in the body. Use the header when you can.
{% endhint %}

## Step 3: Link events to the browser session

Your backend's events and the shopper's browser events are separate streams. To join them, pass the browser's anonymous ID along with the order:

1. **On the storefront**, read the anonymous ID that `@chordcommerce/analytics` gave the shopper. It's in the `__eventn_id` cookie.
2. **Save it on the cart or order** in your platform, for example as a custom attribute, before the shopper reaches checkout.
3. **In your backend**, send it as `anonymousId` on every server event for that order.

Without it, Chord can't connect an order to the browsing and ad clicks that led to it.

## Step 4: Identify the customer

Server events carry no browser context, so destinations that match customers by email, phone or address only get those details if you send them. When an order is placed or an account is created, send an identify call with the customer's details:

```shell
curl -X POST "$CHORD_CDP_DOMAIN/api/identify" \
  -H "Content-Type: application/json" \
  -H "X-Write-Key: $CHORD_WRITE_KEY" \
  -d '{
    "type": "identify",
    "userId": "customer-8812",
    "anonymousId": "a1b2c3d4e5",
    "traits": {
      "email": "customer@example.com",
      "phone": "+12145550100",
      "first_name": "Jane",
      "last_name": "Doe",
      "address": {
        "address1": "12 Test Ln",
        "city": "New York",
        "state": "NY",
        "zipcode": "10001",
        "country": "US"
      }
    }
  }'
```

Use these trait names: `first_name`, `last_name`, and `address1`, `address2` and `zipcode` for addresses. Always include `email` if you have it; it's what most destinations match on. See the [Context object](/collect-data/everyone-else/sdk-reference/context-object.md) for every trait.

An identify call updates the customer's profile. It isn't an event, so it can't trigger automations in destinations. On account creation, send both an identify and a User Created event.

## Step 5: Verify

1. Send a test Order Completed from your backend.
2. In Chord, open **Live Events** for your back-end source and check that it arrived with the right properties.
3. Place a real test order through your storefront, and check that its Order Completed carries the same `anonymousId` as the browser events from that session.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.chord.co/collect-data/everyone-else/server-events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
