Alerts API
Rules on a currency pair that notify a phone when the rate crosses a level.
/v1/alertsNot counted in your quota4 endpointsA rule says: tell me when EUR/USD rises above 1.1000. We check every rule against the rates of the Currencies API every 20 minutes, so a notification can arrive about 22 minutes after the crossing. Alerts are made for moves over a day, not for trading by the minute.
Rules belong to a device, an identifier you choose. Everything is scoped to your API key: two keys can use the same device identifier and never see each other's rules. Times are UTC, ISO 8601 with a Z.
How a rule fires
- A rule fires when the rate crosses the target, then goes quiet.
- It is ready to fire again once the rate moves back past the target plus a 0.15% buffer, so a rate resting on the level cannot flap.
isEnabledis yours and we never change it. A rule that fired stays enabled and fires again on the next real crossing.- At least 6 hours separate two notifications for the same rule.
- A rule whose condition is already true when you create it waits for a real crossing rather than notifying at once.
- Changing a rule's pair, direction or target starts it over. Switching
isEnabledoff and on does not.
PUT into a GET and drop the body.Register a device
Register a device, or refresh its push token and details.
| deviceIdRequiredstring | Your own identifier: up to 255 letters, digits, ., _, : or -. Make it unguessable, such as a UUID: it is the only key to the device's rules |
| fcmTokenstring or null | Push token. null clears it |
| platformstring | ios, android, web or server |
| localestring | Device language, up to 10 characters, such as en or zh-Hans |
| appVersionstring | Your app version, up to 20 characters |
Every field is optional, and only what you send changes. It is safe to retry and to call on every launch. A fresh token clears earlier delivery failures.
{ "fcmToken": "YOUR_DEVICE_PUSH_TOKEN", "platform": "ios", "locale": "en", "appVersion": "1.4.0" }
curl -X PUT "https://api.calenzy.app/v1/alerts/devices/9C2B7C9E-1F41-4A57-B21D-1B8A2C0F4711" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fcmToken": "YOUR_DEVICE_PUSH_TOKEN",
"platform": "ios",
"locale": "en",
"appVersion": "1.4.0"
}'{ "status": "success" }
Replace rules
Send the device's complete list of rules, up to 20.
| deviceIdRequiredstring | As registered |
| idRequiredstring | An uppercase UUID you create. It names the rule and comes back in the notification |
| baseCurrencyRequiredstring | Three letter code from List currencies |
| targetCurrencyRequiredstring | Three letter code, different from baseCurrency |
| directionRequiredstring | above or below |
| targetRateRequirednumber | The level to watch, a positive decimal: the same value as Rate for one pair |
| isEnabledboolean | true by default. A disabled rule is stored but never checked |
| createdAtstring | ISO 8601 date, used to order the list |
The stored list, as Read rules returns it, so you need no second call.
[ { "id": "A1B2C3D4-0000-4000-8000-000000000001", "baseCurrency": "EUR", "targetCurrency": "USD", "direction": "above", "targetRate": 1.2000, "isEnabled": true, "createdAt": "2026-08-25T09:12:33Z" } ]
curl -X PUT "https://api.calenzy.app/v1/alerts/devices/9C2B7C9E-1F41-4A57-B21D-1B8A2C0F4711/rules" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"id": "A1B2C3D4-0000-4000-8000-000000000001",
"baseCurrency": "EUR",
"targetCurrency": "USD",
"direction": "above",
"targetRate": 1.2000,
"isEnabled": true,
"createdAt": "2026-08-25T09:12:33Z"
}
]'[ { "id": "A1B2C3D4-0000-4000-8000-000000000001", "baseCurrency": "EUR", "targetCurrency": "USD", "direction": "above", "targetRate": 1.2, "isEnabled": true, "createdAt": "2026-08-25T09:12:33Z", "lastTriggeredAt": null, "lastTriggeredRate": null } ]
Read rules
The device's rules, with when each one last fired.
| deviceIdRequiredstring | As registered |
Every field you sent, plus the only two we add:
| lastTriggeredAtstring or null | When the rule last fired, UTC. null if it never has |
| lastTriggeredRatenumber or null | The rate at that moment. null if it never fired |
curl "https://api.calenzy.app/v1/alerts/devices/9C2B7C9E-1F41-4A57-B21D-1B8A2C0F4711/rules" \ -H "Authorization: Bearer YOUR_API_KEY"
[ { "id": "A1B2C3D4-0000-4000-8000-000000000001", "baseCurrency": "EUR", "targetCurrency": "USD", "direction": "above", "targetRate": 1.2, "isEnabled": true, "createdAt": "2026-08-25T09:12:33Z", "lastTriggeredAt": null, "lastTriggeredRate": null }, { "id": "A1B2C3D4-0000-4000-8000-000000000002", "baseCurrency": "EUR", "targetCurrency": "USD", "direction": "above", "targetRate": 1.1, "isEnabled": true, "createdAt": "2026-08-24T08:00:00Z", "lastTriggeredAt": "2026-08-25T07:30:20Z", "lastTriggeredRate": 1.16582624 } ]
Forget a device
Delete a device and every rule on it.
Use it when someone uninstalls the app or switches alerts off for good. It cannot be undone. To remove the rules and keep the device, send an empty list to Replace rules.
| deviceIdRequiredstring | As registered |
curl -X DELETE "https://api.calenzy.app/v1/alerts/devices/9C2B7C9E-1F41-4A57-B21D-1B8A2C0F4711" \ -H "Authorization: Bearer YOUR_API_KEY"
{ "status": "success" }
Errors
We check everything before writing, so a refused PUT leaves the stored rules exactly as they were. Besides these, any call can answer one of the common errors.
| Code | HTTP | When |
|---|---|---|
bad_request | 400 | A malformed body or device ID, a missing or invalid rule field, a repeated rule id, a target that is not a positive number, or more than 20 rules |
invalid_currency | 400 | A currency code the Currencies API does not carry |
same_currency | 400 | baseCurrency and targetCurrency are the same |