Birthdays and anniversaries
Collect a birthday, an anniversary or any yearly date for a customer and reward it once a year, at a local time in the customer's time zone.
A customer can hold yearly dates: a birthday, an anniversary, or any key you define such as
pet_birthday. A rule with a date_attribute schedule fires for each customer on that day, once
per calendar year, at a local time in the customer's time zone. The reserved key signup needs no
collection: it is the day the customer was created.
Collect a date
From your backend, with a secret key that has customers:write:
curl -X POST https://api.orishare.com/v1/customers/reader_42/dates/birthday \
-H "Authorization: Bearer $ORISHARE_SECRET_KEY" \
-H "Idempotency-Key: birthday-reader-42" \
-H "Content-Type: application/json" \
-d '{ "month": 3, "day": 14 }'The path takes the customer id or your external id. year is optional; without it, 29 February is
accepted. Send "set_by": "import" when you load dates you already hold. GET on the same path
reads one date and DELETE removes it. Setting a date again with the same value changes nothing.
From your product, a signed-in customer sets their own date with a customer session:
curl -X POST https://api.orishare.com/v1/customer/dates/birthday \
-H "Authorization: Bearer $ORISHARE_PUBLISHABLE_KEY" \
-H "X-Orishare-Customer-Token: $CUSTOMER_TOKEN" \
-H "Idempotency-Key: 6f1c2a9e" \
-H "Content-Type: application/json" \
-d '{ "month": 3, "day": 14 }'GET /v1/customer/dates returns the customer's dates, including the read-only signup date. Each
date says whether it is editable and, after a change, when the customer may change it again
(customer_change_allowed_at).
A customer can always set birthday and anniversary. A custom key becomes available to
customers once a published rule reads it; your backend can set any key at any time.
Reward the day
{
"schema": "orishare.rule/v2",
"trigger": {
"kind": "schedule",
"schedule": {
"key": "birthday",
"kind": "date_attribute",
"attribute": "birthday",
"at": "09:00",
"min_notice": "30d"
}
},
"actions": [
{ "type": "points.award", "currency": "points", "amount": 250, "reason": "Happy birthday" },
{
"type": "webhook.emit",
"event": "customer.birthday",
"payload": { "customer_id": "customer.id" }
}
]
}| Field | Meaning | Default |
|---|---|---|
attribute | The date key: birthday, anniversary, your own key, or signup. | required |
at | Local time of day, HH:MM. | 09:00 |
offset | Fire this long before the day, for example 7d for an early reminder. At most 180d. | none |
min_notice | A date set or changed later than this before the day is not rewarded that year. At most 365d. | 30d |
The local time is taken in the customer's time zone when the customer has one, otherwise in the
environment's time zone. A 29 February date fires on 28 February in years without a leap day. A
signup rule fires on each anniversary of the creation day, starting the year after.
Subscribe a webhook endpoint to the event your rule emits (customer.birthday above) to send the
birthday message from your own email or messaging tool.
What stops abuse
These limits are fixed. They are the same for every environment.
- Once a year. A rule rewards a customer at most once per calendar year. Changing or removing the date afterwards cannot earn that year's reward a second time.
- Notice. A date set or changed with less notice than
min_noticeis skipped for that year. With the default, a birthday entered today is first rewarded when it is at least 30 days away. This applies to every source, including imports; lowermin_noticeon the rule if you trust the dates you load. - Customer changes. A customer sets a date freely the first time and may correct it once. After a change, the next change is possible 365 days later. Your backend is never limited, and a change it makes does not use up the customer's correction.
- Checked when it fires. If the date changes between scheduling and the firing time, that year's reward is skipped rather than sent for a day that no longer applies.
- A customer holds at most 20 stored dates.
Scheduling looks two days ahead, so a date is picked up in time in every time zone. A firing time missed by less than a day (for example during maintenance) is still delivered; older ones are not replayed.
Dynamic segments
Segments defined by conditions over attributes, balances, tiers, account age and event activity, recomputed on a schedule and usable as any audience.
Shopify and Stripe connectors
Turn verified Shopify orders and Stripe billing events into trusted loyalty events, and let customers spend store credit at Shopify checkout.