client.Alerts manages price alerts. An alert watches one market's last traded price or index
price and fires once when the price crosses its level: "above" fires at or above the price, "below" at or below it. A fired alert is delivered in-app, to the account's linked Telegram
account, or both.
Alerts belong to the Main Account. Use an API key of the Main Account; a key scoped to a
sub-account is refused with an *errors.AuthError whose errors.AlertErrorCode is SUBACCOUNT_KEY_REFUSED.
Methods
Create(ctx, services.CreateAlertParams): Create an alert on one market (SymbolorSymbolID). Returnsmodels.PriceAlert.List(ctx, services.ListAlertsParams): One page of your alerts, newest first. Returnsmodels.PriceAlertsPage.All(ctx, services.ListAlertsParams): Every alert matching theListfilters, fetching pages as needed.Update(ctx, services.UpdateAlertParams): Change the direction, price, or channels. Returnsmodels.UpdatePriceAlertResult.Cancel(ctx, alertID): Cancel an alert. Returnsmodels.PriceAlert.
Create
symbol := "BTC-USDT"
alert, err := client.Alerts.Create(ctx, services.CreateAlertParams{
Symbol: &symbol,
Direction: "above",
Price: models.PriceFromDecimal("70000"),
Channels: []string{"in_app", "telegram"},
PriceSource: "last", // or "index"; empty lets the server choose
IdempotencyKey: "btc-70k-alert",
})
if err != nil { log.Fatal(err) }
fmt.Println(alert.AlertID, alert.Status, alert.Armed, alert.ReferencePrice.Ticks())Price is a models.PriceInput, as for orders; reads return models.PriceTicks. An empty PriceSource uses the index price where the market has one, the last traded price otherwise; the
returned alert states it. The current price is recorded as ReferencePrice; an alert whose
condition already holds starts with Armed false and fires only after the price moves back and
crosses again. IdempotencyKey makes a retry of the create safe.
List
page, err := client.Alerts.List(ctx, services.ListAlertsParams{
Statuses: []string{"active"},
Symbol: &symbol,
Limit: 50,
})
if err != nil { log.Fatal(err) }
for _, item := range page.Alerts {
fmt.Println(item.AlertID, item.Direction, item.Price.Ticks(), item.Status)
}
for item, err := range client.Alerts.All(ctx, services.ListAlertsParams{Statuses: []string{"triggered"}}) {
if err != nil { log.Fatal(err) }
fmt.Println(item.AlertID, item.TriggeredAt, item.TriggeredPrice)
}Statuses takes "active", "triggered", and "cancelled". Note the spelling: alerts use "cancelled", unlike a trigger's "canceled". Limit is at most 200; 0 lets the server use 50.
Pass NextPageToken back as PageToken with the same filters.
Update and cancel
newPrice := models.PriceFromDecimal("72000")
result, err := client.Alerts.Update(ctx, services.UpdateAlertParams{
AlertID: alert.AlertID,
ExpectedRevision: alert.Revision,
Price: &newPrice,
IdempotencyKey: "btc-72k-alert",
})
if err != nil { log.Fatal(err) }
fmt.Println(result.Outcome, result.Alert.Revision)
canceled, err := client.Alerts.Cancel(ctx, alert.AlertID)
if err != nil { log.Fatal(err) }
fmt.Println(canceled.Status)Update sends only the fields you set. With none, it sets a triggered alert again as it is. ExpectedRevision is the Revision from your last read and is required; a stale one is refused
with REVISION_CONFLICT. Outcome is "applied", "unchanged", or "replayed" (the idempotency
key was already used for this request): tell a retry from a fresh change by Outcome, never by Revision. Cancelling a cancelled alert returns it unchanged, so a retry is safe.
Errors and retries
Read a refusal's contract code with errors.AlertErrorCode(err) and compare it with the errors.AlertCode* constants.
PRICE_UNAVAILABLE: A retryable*errors.ServerError; nothing changed.SERVICE_UNAVAILABLEonCreate,Update, orCancel: a*errors.ServerErrorwhose outcome is unknown. Send a create or update again with the sameIdempotencyKey, cancel again, or read the alerts back.IDEMPOTENCY_CONFLICT: The key was already used for another request; the original stands.ALERT_TRIGGERED/ALERT_CANCELLED: The alert already fired or was cancelled.
Related
- Errors
- Social verification for the Telegram link