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

# How each send is identified

> Why a Transactional asks which field identifies each send, and what happens when an event arrives twice.

Every Transactional asks one question besides the event and the messages:
**what identifies each send?** The answer is a field of your event, and it
decides how many messages a customer gets.

## The short version

Pick the field that is **different on every event**, usually an id:
`paymentLinkId`, `orderId`, `appointmentId`.

* Each distinct value sends its messages **once, ever**, per customer.
* The same value arriving again for that customer sends **nothing**.
* Two different values for the same customer send **two** messages, even at the
  same time.

## An example

Your system records a `payment_link_created` event each time a payment link is
made, and the Transactional identifies each send by `paymentLinkId`.

| Event received | `paymentLinkId` | What Boom does |
| - | - | - |
| Ana's first link | `pl_1` | Sends the messages |
| Ana's second link, a minute later | `pl_2` | Sends the messages again, for this link |
| A retry of Ana's first link | `pl_1` | Nothing: `pl_1` already sent |

Without that field, Boom could not tell a new payment link from a retry of an
old one, and would either message the customer every time your system retries
or only once for all of their links.

## Choosing the field

* **Use an id that your system creates once per thing**, the same one you would
  use to look it up later.
* **Do not use a field shared by many events**, like the customer id, a status
  or an amount. A customer id would send only the first message the customer
  ever gets, and never again.
* **Do not use a field that changes on a retry**, like a timestamp or a request
  id. Every retry would send again.

When the event has exactly one field ending in `Id`, Boom picks it for you. If
your event has not arrived yet, type the field's name; it only has to match
what your system will send.

## Sending the field

Put the field in the event's `properties`:

```json theme={null}
{
  "name": "payment_link_created",
  "externalId": "evt_001",
  "personExternalId": "cus_42",
  "properties": {
    "paymentLinkId": "pl_1",
    "paymentUrl": "https://pay.example.com/pl_1"
  }
}
```

An event that arrives **without** the field, or with an empty one, sends
nothing, because Boom cannot tell which send it belongs to. So does a value
longer than 255 characters.

<Note>
  `externalId` is a different thing: it identifies the event record itself, so
  recording the same `externalId` twice stores it once. The field that
  identifies each send is what stops a customer from getting the same message
  twice.
</Note>

See [Send transactional messages](/transactional-messages) for the full set-up,
and [events](/events) for the event API.
