Examples
Below are a collection of examples showing Bell in action. These files are pulled directly from the examples/ directory of the repository.
Basic GET Request
A simple example of setting a URL and parameters, then executing a GET request.
# define a variable
id = 123456
# setup a request by defining a url and a param
url "https://httpbin.org/get"
param "id" 1245
# write the HTTP method to send the request
GET
# if the request is the last line of the file, then Bell will log the response
# bell will not log a response if you do anything afterUser Input
Prompt the user for data during execution.
# define a variable using user input
id = input("Enter post id")
url "https://httpbin.org/get?id={id}"
GETSearch with URL Breakdown
Build a URL from a base domain and query parameters.
url "https://httpbin.org/get"
param "page" 2
param "query" "Sushi"
param "location" "NY/New_York"
GETLogin and POST (Single File)
A multi-step workflow in a single file: log in, save the token, then make an authenticated POST.
# pretend authentication, the response will return a token that we can use in the next request
url "https://httpbin.org/anything"
body {
"username": "testuser",
"password": "testpass",
"token": 123456
}
POST
# response is a reserved constant (like "this" and "super")
# save a variable using the response
token = response.body.json.token
log token
# start a new request
url "https://httpbin.org/anything"
# use the token in the headers
headers {
"Authorization": `Bearer: {token}`
}
# use the input("prompt") to prompt the user and wait for input
title = input("Write a title")
body {
"title": title,
"message": input("Write a message")
}
POST
# response is set to the latest response
log responseMulti-file Organization
Bell runs each file in order at the time it is called. If you need to login before executing a file, you can simply import the login.bel file then run a new request.
To ensure that necessary variables are set, you can require them in files and export them in files run before. If the required variable is not present then the execution stops.
Split scripts into reusable files. The main file uses run to run each step; exported variables carry over between files.
# first run the login
run "./1-login.POST.bel"
# post requires token, set in login
run "./2-post.POST.bel"
# id would typically come from a prior response; set it here for the delete
id = 123
# delete requires token and id
run "./3-delete.DELETE.bel"
# load credentials from another Bell file (use run for .bel files, not import)
run "./cred.bel"
# define the route
url "https://httpbin.org/post"
# username: define username in a "./priv.bel" file, DO NOT commit to git
# password: see username error
body {
"username": username,
"password": password
}
# send the request
POST
# extract data from the response and define it
token = response.body.json.username
export token
###
at the beginning, say that we require token to be defined
notice that we could use import instead
however import runs the file associated with the import
require simply ensures that this variable has been set by the time this file is run
###
require token
url "https://httpbin.org/post"
headers {
"Authorization": `Bearer: {token}`
}
body {
"test": input("Write a post")
}
POST
require token
require id
url "https://httpbin.org/delete?id={id}"
headers {
"Authorization": `Bearer: {token}`
}
DELETE
username = "testuser"
password = "secret"
export username, passwordPost with Validation
Import JSON data, validate it against a TypeScript type, and assert on the response.
import requestBody from "./request.json"
# Import Zod schemas for request and response validation
import { EndpointRequestBody, EndpointResponseBody } from "./schemas.ts"
# Validate the request body matches the schema before sending
validate requestBody as EndpointRequestBody
url "https://httpbin.org/post"
body requestBody
POST
# Validate the response shape — catches API contract changes early
validate response.body as EndpointResponseBody
# Log body status for debugging
log response.body.json.status
# Assert the value is what we expect
expect response.body.json.status === "Valid"{
"name": "Gemini",
"status": "Valid"
}Environment Switching
Load an environment config and let the user choose between dev, staging, and production.
# import your environments
import "envConfig.json"
# prompt the user to choose an environment
# the env's "url" key becomes the base URL for path statements
env "dev" | "preprod" | "prod"
# path is combined with the base URL from the selected environment
path "/post"
POST{
"dev": {
"url": "https://httpbin.org"
},
"preprod": {
"url": "https://httpbin.org"
},
"prod": {
"url": "https://httpbin.org"
}
}Security Warnings
Use warn to require confirmation before sending a request to a sensitive endpoint.
# warn will prompt the user to validate before sending each request
# that contains the prodUrl variable
prodUrl = warn "httpbin.org"
id = 1234
url "https://{prodUrl}/delete?id={id}"
# warning will look like:
# Warning: you are about to send a POST request to prodUrl: [httpbin.org]
# Please confirm before continuing (Y to continue, any other key to cancel)
POST