Bash and REST API: Calling and Handling APIs Effectively in DevOps
Comprehensive guide to calling REST APIs with curl in Bash: GET/POST/PUT/DELETE, JSON parsing with jq, bearer auth, retry logic, and automating GitHub/Slack APIs in DevOps.
In the previous post, we explored optimizing performance with Parallel Execution. Now, we combine Bash with REST APIs—the bridge to communicating with nearly every modern service: from GitHub, Slack, and Jira, to monitoring dashboards and CI/CD platforms.
In DevOps, APIs are the way to fetch data, check status, or remotely control systems. And Bash is the perfect tool for calling APIs—curl is available on every server, jq parses JSON lightning-fast, and you can integrate it into any script without installing additional libraries or frameworks.
This article covers calling APIs with curl, parsing JSON responses with jq, handling authentication, implementing retry logic, and includes a practical script for automatically creating GitHub Issues when deploys fail.
Calling APIs with curl
Basic Methods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# GET — retrieve datacurl -s "https://api.example.com/status"# POST — create new datacurl -s -X POST \
-H "Content-Type: application/json"\
-d '{"title": "Bug report", "body": "Something went wrong"}'\
"https://api.example.com/issues"# PUT — update existing datacurl -s -X PUT \
-H "Content-Type: application/json"\
-d '{"status": "resolved"}'\
"https://api.example.com/issues/42"# DELETE — remove datacurl -s -X DELETE "https://api.example.com/issues/42"
# Example: API health check with timeout and retryHTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}"\
--connect-timeout 5 --retry 3 --retry-delay 2\
"https://api.example.com/health")if[["$HTTP_CODE" -eq 200]];thenecho"API is healthy"elseecho"API returned status $HTTP_CODE"fi
JSON Parsing with jq
jq is a lightweight command-line JSON processor—extremely powerful when combined with curl.
# Get repo name and star count from GitHub APIREPO_INFO=$(curl -s "https://api.github.com/repos/cli/cli")NAME=$(echo"$REPO_INFO"| jq -r '.full_name')STARS=$(echo"$REPO_INFO"| jq -r '.stargazers_count')echo"$NAME has $STARS stars"# List open issuescurl -s "https://api.github.com/repos/owner/repo/issues?state=open"|\
jq -r '.[] | "[\(.number)] \(.title)"'# Get latest commit messagecurl -s "https://api.github.com/repos/owner/repo/commits?per_page=1"|\
jq -r '.[0] | "\(.commit.author.name): \(.commit.message)"'
Retry Logic in Bash
When calling APIs from scripts, networks can have intermittent failures. Retry logic enables automatic retries:
# GitHub Actions exampledeploy:script:- bash deploy.shafter_script:- | if [[ "$CI_JOB_STATUS" == "failed" ]]; then
bash .github/scripts/github-issue-on-failure.sh "Deploy job failed"
fi
Sample Output
1
2
Creating GitHub issue for failed deploy...
[INFO] Created issue #247: https://github.com/org/repo/issues/247
The GitHub Issue is created with:
Title: [DEPLOY FAIL] production — a1b2c3d — 2026-09-03
Labels: auto-deploy-failure, ops
Body containing environment, commit info, pipeline URL, and checklist
Deployment Notes & Best Practices
Token security: Always store GITHUB_TOKEN as a secret variable—never hardcode it in scripts. GitHub tokens need the repo scope to create issues.
Duplicate prevention: The script checks for duplicate issues before creating—preventing spam when pipelines fail repeatedly in succession.
jq dependency: Ensure jq is installed on the runner/CI machine. Most CI images include it, but if not, add apt-get install -y jq to the pipeline.
Rate limiting: GitHub API has rate limits (5000 requests/hour for authenticated users). This script makes few requests so it’s not an issue, but when writing scripts that call APIs heavily, check the X-RateLimit-Remaining header.
Multi-platform: The script uses GitHub API, but you can replace endpoints to create issues on GitLab, Jira, or any issue tracking system with a REST API.
Conclusion
Bash and REST API is an extremely powerful combination in DevOps. From simple API calls with curl, complex JSON parsing with jq, retry logic implementation, to automatically creating GitHub Issues on deploy failures—all can be accomplished with just Bash without heavy frameworks.
In the next post, we will explore Bash and Cloud CLI: managing AWS, GCP, Azure from Bash, querying JSON output, and automating cloud tasks.