← tickerbot.io
View as markdown

Update a custom signal

PATCHhttps://api.tickerbot.io/v2/signals/{signal}

Update a custom signal you own — its expression, description, or name.

stringrequired

Custom signal slug (the signal name). A built-in name answers 404 — built-ins are read-only.

string

New SQL expression. Re-validated and re-inlined against your other custom signals. Same strict grammar as create — no LIKE/ILIKE, CASE, :: casts, or functions beyond abs/coalesce/round/least/greatest. The response echoes your expression as stored, not its expansion (a pre-2026-09-07 column spelling is stored under its current name and reported in _meta.deprecated_columns).

string

New description. Not derived from expr — change both if the prose describes a threshold you are moving.

string

New slug — renames the signal and changes its API handle everywhere (same validation as create). Refused while other custom signals reference the current name. name is accepted as an alias (new_name wins when both are sent), but new_name is the unambiguous spelling since the URL already carries the current name.

as_ofstring

Server time this response was assembled (ISO 8601).

signalobject

The stored signal: `name`, `kind` (`custom`), `description`, `expr` (your predicate as stored), `created_at`, `updated_at`.

_metaobject

Only when `expr` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored `expr` carries the current name.

200
{ as_of, signal: {...} } — the updated signal. A request that changes nothing (empty body, or name equal to the current name) is also a 200 carrying the signal unchanged, and does not touch updated_at.
400
compile_failed on bad expression, bad_request on shape failure or an unknown body key (strict — unknown fields are rejected, not ignored). The accepted keys are description, expr, new_name, and name (the legacy alias of new_name).
404
not_found — no custom signal with that name on this account, OR the name is a built-in: digit-leading names like 52_week_high can only be built-ins (create forbids the shape), so they answer "built-ins are read-only" rather than a misleading validation error.
409
rename_blocked (other custom signals reference the current name — listed in references.signals), name_collision (new name is a built-in signal), or already_exists (you already have a signal with the new name).
  • Partial update: supply expr, description, new_name, or any combination. Providing expr recompiles against the live signal whitelist, the same validator as create. Built-in signals are read-only — only your own custom signals can be patched.
  • The name IS the signal's API handle. Renaming via new_name changes what you reference in q and the CRUD path itself, so old-name references in your code stop compiling. Rename is refused with 409 rename_blocked while other custom signals of yours reference the current name (edit those first), and with 409 name_collision / already_exists if the new name hits a built-in signal or a signal you already have.
  • Existing subscriptions do not change. The subscribe endpoints freeze a custom signal's SQL into the webhook at creation, so editing or renaming here updates ad-hoc reads and *new* subscriptions while already-created webhooks keep firing on the old definition. Re-subscribe to apply.