Skip to content

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.

bel

# define a variable
id = 123456

# setup a request by defining a url
# anything in {} will be replaced with a variable
url "http://localhost:4000/post/{id}"

# 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 (writing: "log response" is unnecessary)
# bell will not log a response if you do anything after

User Input

Prompt the user for data during execution.

bel

# define a variable using user input
id = input("Enter post id")

url "http://localhost:4000/post/{id}"

GET

Search with URL Breakdown

Build a URL from a base domain and query parameters.

bel

url "https://preprod.bell.com/restaurants/search"

param "page" 2
param "query" "Sushi"
param "location" "NY/New_York"

GET

Login and POST (Single File)

A multi-step workflow in a single file: log in, save the token, then make an authenticated POST.

bel
url "http://localhost:4000/login/"

body {
  "username": "testuser",
  "password": "testpass"
}

POST

###
because there are more commands afterward
the login POST request will not be logged
###

# save a variable using the response
token = response.body.token

# start a new request
url "http://localhost:4000/post/"

# use the token in the headers
headers {
  "Authorization": `Bearer: {token}`
} 

title = input("Write a title")

# use the input("Prompt") to prompt the user and wait for input
body {
  "title": title,
  "message": input('Write a message')
}

POST

# response is a reserved constant (like "this" and "super")
# response is set to the latest response
log response.body.status

# you can also log the url
log url

Multi-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 request to run each step; exported variables carry over between files.

bel

# first run the login
request "./1-login.POST.bel"

# post requires token, set in login
request "./2-post.POST.bel"

# delete requires token and id
request "./3-delete.DELETE.bel"
bel

# import variables from another bell file
import { username, password } from './cred.bel'

# define the route
url "http://localhost:4000/login"

# username: define username in a "./priv.bell" 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.token
export token
bel

###
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 "http://localhost:4000/post"

headers
{
  Authorization: `Bearer: {token}`
} 

body {
  test: input("Write a post")
}

POST
bel

require token
require id

url "http://localhost:4000/post/{id}"

headers
{
  Authorization: `Bearer: {token}`
} 

DELETE
bel

username = "testuser"
password = "secret"

export username, password

Post with Validation

Import JSON data, validate it against a TypeScript type, and assert on the response.

bel
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"
json
{
  "name": "Gemini",
  "status": "Valid"
}

Environment Switching

Load an environment config and let the user choose between dev, staging, and production.

bel

# import your environments
import "envConfig.json"

# use env to prompt the user to choose an environment before running
# this will set domain
# this will also set specified vars
env

# use env with delineators to give the user options
env "dev" | "preprod" | "rc" 

# or use env to set the environment
env "preprod" 

# env will set domain
path "/admin/user/suspend"

POST
json
{
  "dev": {
    "url": "localhost:4001"
  },
  "preprod": {
    "url": "preprod.com"
  },
  "prod": {
    "url": "prod.com"
  }
}

Security Warnings

Use warn to require confirmation before sending a request to a sensitive endpoint.

bel

# warn will prompt the user to validate before sending each request
# that contains the prodUrl variable
prodUrl = warn "production.com"

id = 1234

url "https://{prodUrl}/user/delete/{id}"

# warning will look like:
# Warning: you are about to send a POST request to prodUrl: [production.com]
# Please confirm before continuing (Y to continue, any other key to cancel)
POST