Notifications
Send a message to your own user and let them decide where it lands.
Your site can send a message to a person who signs in with auth.my — an order shipped, an invoice issued. They receive it in their auth.my account, and by email if they allow it.
The point is not delivery: you can send email yourself. The point is the decision. The person has one list of senders instead of a settings page hidden in each of your competitors' accounts, one "nothing from this site" switch that always works, and an unsubscribe link that says what exactly it turns off. You get all of that without a mail service, an address list or a consent page of your own.
The request
POST https://auth.my/api/notify
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/json
{
"sub": "9f1c…",
"category": "transactional",
"title": "Order 123 is on its way",
"body": "It will arrive on Thursday.",
"url": "https://shop.example/orders/123"
}
sub is the identifier you got in the ID token. title is up to 120
characters, body up to 2000. url is optional and must point at your own
site — a link in a letter from our address reads as ours, so we do not put
somebody else's there.
Only url becomes a clickable link in the letter: an address in body,
even with https://, arrives as plain text — the way you wrote it — and is
never turned into an anchor. Only url gets its host checked, so only url
becomes a link.
An address or an IP written without https:// in title or body still
reaches the letter as text, but gets an invisible separator inside it, so
the mail client does not turn it into a link on its own. Ordinary text is
left alone: the separator only goes into something that looks like a whole
domain in a known zone or a whole IPv4 address, not after every dot —
"version 1.2" and "report.pdf" arrive unchanged.
The list of known zones is finite, not exhaustive: evil.click or
evil.zone fall outside it and get no separator. A version number of
exactly four segments, each within 0-255 (1.2.3.4), is indistinguishable
from a real IPv4 address and gets the same separator.
The answer is 202 and tells you what happened:
{ "inApp": true, "email": false, "skipped": null }
skipped is muted when the person silenced your site, category_off when
they turned this kind off, no_email when there is nowhere to write. None of
these is an error: it is their decision, and the sensible response is to stop
sending that kind, not to retry.
Categories
| Category | What it is for | Default |
|---|---|---|
transactional | Orders, invoices, appointments — what they came for | account and email |
product | What changed in your service | account only |
promotions | Advertising | off |
Advertising is off until the person turns it on. Consent to a mailing list is given by the one who receives it.
Refusals
| Code | Meaning |
|---|---|
401 invalid_client | Wrong client, wrong secret, or the application is public. Only a confidential client can send. |
403 not_connected | This person never signed in to you, or revoked the access. |
400 url_not_allowed | The link points somewhere other than your site. |
400 unknown_category | There is no such category. |
What we do not do
We do not translate your text: "order 123 shipped" is yours, and machine translation of it would be worse than none. The letter is therefore bilingual — your message in your words, and everything around it (who it is from, why it arrived, how to stop it) in the language of the reader.
There is no push and no SMS. Push needs a delivery service and keys we do not have, and announcing a channel that delivers nothing is a lie in the settings. SMS is busy with sign-in codes: sending offers through it is the fastest way to make our codes stop arriving.