Skip to content

Sharing Consignee Engagement Data

When you send your own invites, host the tracking experience in your own website or app, or collect ratings with your own tool, Bettermile no longer sees how consignees engage with their parcels. Sharing that engagement data closes the loop: it lets Bettermile measure the tracking experience end to end, compare channels, and improve ETAs and features for your consignees.

You share it by sending one request per parcel and day to the consignee engagement webhook.

When you need it

Share engagement data if any of the following is true for your integration:

What you send

Each request describes one parcel on one day. Only tenantId, parcelNumber and date are required. All other sections are optional: send only the ones you collect. For example, if you only send your own invites, send only invites; if you only run your own feedback tool, send only ratings.

SectionWhat it describes
invitesThe tracking invite you sent: channel, whether it was delivered, opened and clicked.
clicksEvery visit to the tracking page or app, with the ETA window the consignee saw and how they arrived (utmSource).
ratingsThe rating and feedback the consignee gave, including the scale and the tool used.
outOfHomeAn out-of-home delivery option the consignee chose, such as a parcel locker or a safe place.
otherFeaturesOther tracking features the consignee used, such as the map view.

The Consignee Engagement API reference lists every field, its format and the allowed values, with an example request for each section on its own.

The example below shows a tenant that sends its own invites, hosts the tracking page and collects ratings:

{
    "tenantId": "gls-de",
    "parcelNumber": "P123456789",
    "date": "2026-09-16",
    "invites": {
        "createdAt": "2026-09-16T09:06:00Z",
        "inviteMedium": "EMAIL",
        "destinationUrl": "https://www.example.com/track/P123456789",
        "delivered": true,
        "opened": true,
        "clicked": true
    },
    "clicks": [
        {
            "createdAt": "2026-09-16T09:20:00Z",
            "platform": "WEB",
            "url": "https://www.example.com/track/P123456789?utm_source=invite-email",
            "etaLowerBound": "2026-09-16T10:15:00Z",
            "etaUpperBound": "2026-09-16T10:35:00Z",
            "utmSource": "invite-email"
        }
    ],
    "ratings": {
        "createdAt": "2026-09-16T12:03:00Z",
        "platform": "WEB",
        "scale": "ONE_TO_FIVE",
        "tool": "STARS",
        "ratingValue": 5,
        "feedbackMessage": "Perfect service!",
        "errors": []
    }
}

How it works

BettermileTenantBettermileTenantEach request replaces the previous onefor the same parcel and dayConsigneeTracking invitePOST /parcel-consignee-engagement (invite)202 AcceptedVisits tracking page, rates deliveryPOST /parcel-consignee-engagement (invite + clicks + rating)202 AcceptedConsignee
BettermileTenantBettermileTenantEach request replaces the previous onefor the same parcel and dayConsigneeTracking invitePOST /parcel-consignee-engagement (invite)202 AcceptedVisits tracking page, rates deliveryPOST /parcel-consignee-engagement (invite + clicks + rating)202 AcceptedConsignee

Send snapshots, not changes

Each request is a snapshot: the complete state of one parcel on one day, not what changed since your last request. Whenever something new happens, send everything you know about the parcel and day again, including all earlier clicks. A later request for the same parcelNumber and date replaces the earlier one, so if you collect several sections, send them together in each request rather than one section per request.

This also makes retries safe: sending the same snapshot twice has no side effects.

You decide when to send. Sending after every new event gives Bettermile the most current picture; sending once at the end of the delivery day is also fine, as long as the snapshot is complete.

Authentication

Requests are authenticated with an API key in the x-api-key header. Bettermile issues one key per tenant; request it from your Bettermile representative. The tenant is taken from the key, so keep it secret and use it only from your backend.

curl -X POST https://data-solutions.bettermile.com/parcel-consignee-engagement \
    -H "x-api-key: $BETTERMILE_ENGAGEMENT_API_KEY" \
    -H "Content-Type: application/json" \
    -d @engagement.json

Validation

The request body is validated strictly. Every object is closed, so a field that is not part of the schema is rejected with 400, as is a wrongly formatted date or a value outside the allowed range. If you want to send data that does not fit the schema yet, contact Bettermile first so the field can be added.

Responses and retries

HTTP statusMeaningWhat to do
202Accepted for storage.Nothing. Do not retry.
400The body failed validation.Fix the request. Do not retry it unchanged.
403The API key is missing, unknown or not allowed to send engagement data.Check the x-api-key header. Do not retry.
429Throttled.Retry with exponential backoff and jitter.
500, 503Temporary failure.Retry with exponential backoff and jitter.

Successful and throttled responses include a requestId. Log it and quote it when contacting Bettermile about a request.

Best practices

  • Send only what you collect. Leave out sections you have no data for instead of sending them empty.
  • Always send the full snapshot. A request with only the newest click replaces the earlier clicks for that parcel and day.
  • Use UTC timestamps in ISO 8601 format, for example 2026-09-16T09:06:00Z.
  • Use the documented values for scale, tool, utmSource, outOfHome.type and featureType, so your data can be compared with that of other channels and tenants.
  • Use the same UTM sources as in your invites, for example utm_source=invite-email and utm_source=invite-sms. See Invites via Tenant.
  • Retry only on 429 and 5xx, with exponential backoff and jitter. Retrying on 400 or 403 will not succeed.
  • Test in the development environment first. Ask your Bettermile representative for a development API key.