Skip to content

CRM gifts

A CRM or marketing automation system sends a gift when a player reaches a journey step, such as a birthday, a deposit milestone, or a win-back. The CRM picks the segment, creates one personal link for each player, and sends it through its own channel.

Requires: a key with the PERSONAL_LINKS scope, and a webhook URL to follow claims.

Ask your Luxorr contact for one campaign for each journey type, such as “VIP birthday” or “Deposit milestone”. A campaign holds the gifts a player can choose from, under one or more of your brands.

To find each campaign’s ID, call GET /campaigns, or copy the ID from the campaign’s page in the Luxorr workspace. Store the ID with the journey step.

Ask your team for an order field that holds your player ID, such as “Customer ID”. GET /me lists it in tenant.customFields, with its id.

When a player reaches the step, create their link:

POST /v1/personal-links
Idempotency-Key: birthday-2026:player-1001
{
"campaignId": "1e2d3c4b-5a69-4c1f-9a52-8d0e4f4b9a3e",
"fullName": "Alice Smith",
"email": "[email protected]",
"message": "Happy birthday from the VIP team!",
"locale": "en-US",
"customFields": [
{ "fieldId": "5c4b3a29-1807-4f6e-8d5c-4b3a29180746", "textValue": "player-1001" }
]
}

Keep the following in mind:

  • Build the Idempotency-Key from the occasion and the player. If the journey runs again for the same player, or your job fails and reruns the segment, the same key returns the first link instead of a second gift. A replay lasts 7 days. After that, the same key creates a new link.
  • After a timeout or a 5xx code, send the same request again with the same key. A different body with the same key returns 422 idempotency_key_reused.
  • After 400 invalid_request, nothing was created. errors[] names each field, for example a language that isn’t enabled for your account (GET /me lists them in tenant.locales), or a missing required custom field. Fix the player’s data, and send the request again.
  • The link lasts as long as its campaign. Its expiresAt shows when it ends, so you can add a “claim by” date to your message. null means no end date. The link expires when the campaign ends or passes that date.

Store the link id and claimUrl with the player.

Put claimUrl in your message: email, push, in-app inbox, or chat. The gift site shows your brand.

If your account requires approval, links start as REQUESTED and the player can’t claim them yet. Send the message after personal_link.approved arrives.

Every event carries the whole link, including its customFields. Match an event to your player by the field that holds your player ID, or by the link id you stored.

The following table shows what each event means for the journey:

Event Meaning
personal_link.approved Your team approved the link. Send it now.
personal_link.claimed The player chose a gift. Mark the step done.
personal_link.cancelled The link was withdrawn. Stop reminders.
personal_link.expired The campaign ended, and the link with it. Stop reminders.
personal_link.created A link was created outside your journey, for example in the workspace. Links that your key created are in the create response and the feed, not in webhooks.

If your system processes events in batches, read the event feed on a schedule instead. The feed keeps 30 days of events and is the way to sync link changes.

To send a reminder, use the same claimUrl. To withdraw a link that your key created, call POST /personal-links/{linkId}:cancel with a reason. A retry is safe with or without an Idempotency-Key. The player then sees the link as expired. If your team created the link, the API returns 409 not_cancellable with reason: "created_elsewhere".