Skip to content

FOBshippingpoint/poorman

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Poorman

A very limited alternative to Postman, powered by curl and POSIX shell.

Who is this for?

Who want to send API requests without feeding the memory. And the one who familiar with shell.

Prerequisites

  • Posix Shell (dash, ksh, bash, zsh, etc.)

  • curl

  • jq (Optional)

    ℹ️

    If jq is installed, Poorman will generate "Rich Snapshots" that include HTTP status codes, timing, and headers alongside the JSON body.

Getting Started

  1. Create a new script: Copy sample.sh to a new file, for example, my_api_tests.sh.

    cp sample.sh my_api.sh
    chmod +x my_api.sh
  2. Set the Base URL: Edit my_api_tests.sh and change the BASE_URL variable to your target API’s base URL.

    BASE_URL=https://api.example.com
  3. Add Requests: Add your API requests using the GET, POST, PUT, PATCH, DELETE requests. You can add any valid curl options after the path.

    # Simple GET request
    GET /users/1
    
    # POST request with a JSON body
    POST /users --json '{"name": "New User"}'
  4. Run the script: Execute your script from the terminal.

    ./my_api.sh
  5. Snapshot Responses: You can add Snapshot after the request. Run the script again, and the response will be captured and embedded directly into the script. This allows you to "record" the server’s response (like Postman’s example).

    GET /users/1
    Snapshot

    After running the script, it will become:

    GET /users/1
    : <<'SNAPSHOT'
    http_code        200
    method           GET
    size_download    509
    time_total       0.479236
    url_effective    https://jsonplaceholder.typicode.com/users/1
    date             Sat, 10 Jan 2026 07:33:15 GMT
    content-type     application/json; charset=utf-8
    -------------------------
    {
      "id": 1,
      "name": "Leanne Graham",
      "username": "Bret"
    }
    SNAPSHOT
    💡

    The : is the shell builtin that almost do nothing. Combined with here-document (<<'SNAPSHOT'), we can have the comment without preceding #.

Example

Here is a more complete example of an API script:

#!/bin/sh

. ./poorman.sh

# /// configurations ///

# Base URL of each requests. Trailing slash is optional.
BASE_URL=https://jsonplaceholder.typicode.com
# Set to 1 if you only want to run requests starts with "Only"
ONLY=
# Set to 1 if you want to see the actual curl commands
DRY_RUN=

# /// curl options ///

# Add global curl option
CurlOptionGlobal --location

# /// hooks ///

AfterHook() {
  # Prints response body for every request
  printf '%s' "$BODY"
}

# /// requests ///

# Add option that only affect next request
CurlOptionOnce --user admin:password

# Get post by id
commentId=1
GET /comments/$commentId
# This line will replaced with the response body of previous request
Snapshot
# Like this:
# : <<'SNAPSHOT'
# http_code        200
# method           GET
# size_download    268
# time_total       0.411915
# url_effective    https://jsonplaceholder.typicode.com/comments/1
# date             Sat, 10 Jan 2026 10:23:10 GMT
# content-type     application/json; charset=utf-8
# -------------------------
# {
#   "postId": 1,
#   "id": 1,
#   "name": "id labore ex et quam laborum",
#   "email": "Eliseo@gardner.biz",
#   "body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
# }
# SNAPSHOT

# Create new post
POST /posts --json "$(
  cat <<'PAYLOAD'
{
  "title": "poorman",
  "body": "A very limited alternative to postman",
  "userId": 1
}
PAYLOAD
)"
Snapshot

# [SKIP] Get album's photo
album=3
Skip GET /albums/$album/photos

# Alter user name
userId=1
PATCH /users/$userId --json '{"name": "John Doe"}'
Snapshot

Reference

Configuration

Name Description Example

BASE_URL

The prefix of all request URLs. A trailing slash (/) is optional.

https://example.com

DRY_RUN

Set to 1 to print the enabled request commands.

0/1

ONLY

Set to 1 to only run the requests starts with Only.

0/1

Request

Method & Syntax Description Example

GET <path> [curl_options…​]

Sends a GET request.

postId=1
GET /posts/$postId

POST <path> [curl_options…​]

Sends a POST request.

POST /posts --verbose --json "$(cat <<'JSON'
{
  "id": 1,
  "title": "foo",
  "body": "bar",
  "userId": 1
}
JSON
)"

PUT <path> [curl_options…​]

Sends a PUT request.

PUT /posts/1 --json "$(cat <<'JSON'
{
  "id": 1,
  "title": "foo",
  "body": "bar",
  "userId": 1
}
JSON
)"

PATCH <path> [curl_options…​]

Sends a PATCH request.

PATCH /albums/1/photos --json '{"date": 1767515098}'

DELETE <path> [curl_options…​]

Sends a DELETE request.

DELETE /posts --url-param 'user=1'

Variables

Name Description

BODY

The response body of latest request.

META_JSON

All curl write-out variables in json format of latest request. (%{json})

HEADER_JSON

curl write-out headers in json format of latest request. (%{header_json})

SNAPSHOT

The content that will be used for constructing Snapshot. Set SNAPSHOT to create custom snapshots in AfterHook.

Modifier

CurlOptionOnce <curl_option…​>

Sets curl options for the next request only.

Example:

# This applies only to the next GET request
CurlOptionOnce --header "X-Custom-Header: value"
GET /some/path

CurlOptionGlobal <curl_option…​>

Sets curl options for all subsequent requests.

Example:

# This applies to all subsequent requests
CurlOptionGlobal --location
GET /some/path

Snapshot

Captures previous request result and replace itself.

GET /users/1
Snapshot

After running the script, it will become:

GET /users/1
: <<'SNAPSHOT'
http_code        200
method           GET
size_download    509
time_total       0.479236
url_effective    https://jsonplaceholder.typicode.com/users/1
date             Sat, 10 Jan 2026 07:33:15 GMT
content-type     application/json; charset=utf-8
-------------------------
{
  "id": 1,
  "name": "Leanne Graham",
  "username": "Bret"
}
SNAPSHOT

Skip <request>

Skips the execution of a request.

Example:

# This request will not be executed
Skip GET /users/1

Only <request>

With ONLY=1 environment variable set. Only the requests wrapped by Only will be executed.

Example:

ONLY=1
Only GET /users/1                         # execute
POST /users --json '{"name": "New User"}' # skipped
Only DELETE /users/2                      # execute
Only GET /users/1                         # execute
POST /users --json '{"name": "New User"}' # execute, since ONLY is not equal to 1
Only DELETE /users/2                      # execute

Hook

BeforeHook

A function that is executed before each enabled request.

AfterHook

A function that is executed after each enabled request. This is useful for processing the response, for example, pretty print only the response body with jq.

Example:

AfterHook() {
  # Pretty-print JSON response using jq
  jq -n --argjson body "$BODY" '$body'
}

About

postman alternative

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors