Skip to content

Fallback Commands

Fire an HTTP request, keep coding. When the response lands, run /onSuccess or /onError automatically. No await, no blocking, no staring at a spinner in your command logic.

That's the fallback command pattern — chain HTTP to other commands using success and error.


How it works

HTTP.get({
  url: "https://api.example.com/todos/1",
  success: "/onSuccess",
  error: "/onError",
  tbl_options: { source: "menu" }
})
Option When it runs
success HTTP status is 2xx (res.ok === true)
error HTTP status is not 2xx (res.ok === false)

The HTTP call returns immediately. Your current command continues. Callback commands run when the response arrives.

If the request fails and error is not defined, no callback command runs. Use await inline when you need to handle failures in the same command.


Passing data with tbl_options

HTTP.post({
  url: "https://api.example.com/order",
  body: { item: params },
  success: "/onOrderDone",
  tbl_options: { item: params, userId: user.id }
})

Inside /onOrderDone, read tbl_options.item and tbl_options.userId. See tbl_options.


Success callback (/onSuccess)

When the request succeeds, these globals are available:

Global Description
http_response Full result wrapper
response Parsed HTTP response object
content Raw body (response.content)
headers Response headers
cookies Parsed cookies
tbl_options What you passed in the request
// Command: /onSuccess
if (response.ok && response.isJson) {
  Bot.sendMessage("Title: " + response.data.title)
} else {
  Bot.sendMessage("Response: " + content)
}

Error callback (/onError)

When the request fails (non-2xx), the error global contains the full HTTP response object:

Field Example
error.status 404, 500
error.ok false
error.content Error body string
error.data Parsed error JSON (if applicable)
error.error.code Machine-readable code (e.g. "TIMEOUT")
error.error.message Human-readable message
// Command: /onError
if (error.status === 404) {
  Bot.sendMessage("Resource not found.")
} else if (error.status === 408 || error.error?.code === "TIMEOUT") {
  Bot.sendMessage("Request timed out.")
} else {
  Bot.sendMessage("Request failed: " + error.status)
}

http_response, response, content, headers, and cookies are also set the same way as in success callbacks.


Inline vs callback

Approach Best for
await HTTP.get(...) Same command needs the result immediately
success / error Fire-and-forget, keep commands short, multi-step pipelines
// Inline — handle in same command
let res = await HTTP.get("https://api.example.com/price")
if (res.ok) Bot.sendMessage("$" + res.data.price)

// Callback — delegate to another command
HTTP.get({
  url: "https://api.example.com/price",
  success: "/showPrice",
  error: "/priceUnavailable"
})

Pick your style. Callbacks keep commands short. Inline keeps everything in one place. Both are valid.


Command chain limit

Each success or error callback counts toward the 6-command chain limit per execution (same as Bot.run). Deep HTTP → command → HTTP chains should be kept shallow. Your future self debugging at 2 AM will appreciate it.


What fallback commands do not catch

Not caught by error callback Handle with
Script errors in the same command ! error handler
Invalid HTTP options (bad URL, etc.) ! error handler (throws before request)
Network-level throws in validation ! error handler

Full pipeline example

// /fetchWeather command
HTTP.get({
  url: "https://api.weather.com/current",
  query: { city: params },
  headers: { "X-Key": process.env.WEATHER_API_KEY },
  success: "/showWeather",
  error: "/weatherError",
  tbl_options: { city: params }
})

Bot.sendMessage("Fetching weather for " + params + "...")
// /showWeather command
let temp = response.data.temperature
Bot.sendMessage(tbl_options.city + ": " + temp + "°")
// /weatherError command
Bot.sendMessage("Could not fetch weather (" + error.status + ")")

Important notes

  • Callback commands have full access to Bot, Api, db, and globals
  • HTTP is not available inside broadcast commands
  • Response globals exist only during callback command execution
  • See Responses for the full response object reference