Try it · no signup, no key
One incident. Four vendors' APIs.
Paste this into a terminal. It follows a single production incident across Slack, Jira, GitHub and GitLab — four different companies' API shapes — and checks that they agree, down to the commit SHA. It takes about ten seconds and asks you for nothing.
#!/usr/bin/env bash
#
# One incident, four vendors' APIs, in about ten seconds. No signup, no SDK,
# no key.
#
# WHAT THIS PROVES, and what it deliberately does not claim. Every value
# compared below is pulled from a LIVE response at run time — nothing compared
# here is a literal in this file. Two of the four hops are genuinely
# discovered: the GitHub issue is found by matching Jira's summary text, and
# the GitLab merge request is found by the branch name GitHub just returned.
# The other two are entry points, and are labelled as such.
#
# It is NOT a claim that the providers hyperlink to each other — they don't,
# any more than the real ones do. The claim is simpler and stronger: four
# different vendors' APIs, asked independently, tell one coherent story, and
# they will still agree in a year, because every host below is a frozen
# snapshot pinned to a content hash.
#
# Exits non-zero if any cross-provider check fails, so this is a real
# assertion and not a demo that prints regardless.
set -euo pipefail
command -v curl >/dev/null || { echo "This needs curl." >&2; exit 127; }
command -v python3 >/dev/null || { echo "This needs python3 (used only to read JSON)." >&2; exit 127; }
SLACK=https://slack-2026-08.snap.sandboxapis.dev
JIRA=https://jira-v3-g6.snap.sandboxapis.dev
GH=https://gh-2026-03-g6.snap.sandboxapis.dev
GL=https://gl-v4-g6.snap.sandboxapis.dev
# The three entry points. Overridable so the failure path is testable — a
# demo whose assertions cannot fail is theatre (scripts/four-hop.test.sh).
CHANNEL=${CHANNEL:-CF1UPUMGC8Q} # the #incident-bridge channel
KEY=${KEY:-FATE-46} # the tracker key
PR=${PR:-47} # the pull request that carried the fix
# Read one value out of a JSON document. python3 is used ONLY as a JSON
# reader — the requests themselves are plain curl, so every URL below is
# something you can paste on its own.
#
# On any failure this reports what the API actually said instead of letting a
# python traceback escape. That matters more here than in most scripts: this
# is the first thing a stranger runs, and a stack trace would read as "the
# product is broken" when the truth is usually "that entry point moved".
#
# need <what-we-wanted> <json> <python-expression>
#
# `fail` runs inside the command substitution's subshell, so it prints the
# message there and exits non-zero; `set -e` then stops the parent.
need() {
printf '%s' "$2" | EXPR="$3" python3 -c "
import json, os, sys
try:
d = json.load(sys.stdin)
print(eval(os.environ['EXPR']))
except Exception:
sys.exit(1)
" 2>/dev/null || fail "$1 — the API answered: $(printf '%s' "$2" | tr -d '\n' | cut -c1-160)"
}
if [ -t 1 ]; then
bold=$(printf '\033[1m'); dim=$(printf '\033[2m')
green=$(printf '\033[32m'); red=$(printf '\033[31m'); off=$(printf '\033[0m')
else
bold=""; dim=""; green=""; red=""; off=""
fi
fail() { echo "${red}FAILED: $1${off}" >&2; exit 1; }
ok() { echo " ${green}ok${off} $1"; }
hop() { echo; echo "${bold}$1${off}"; echo "${dim} \$ curl -s \"$2\"${off}"; }
# An OPTIONAL key, in the variable the docs already name for one
# (/docs/auth, packages/mcp/README.md). The walk still runs without it — that
# is the whole point of the demo — but it spends five anonymous requests, and
# the anonymous budget is 60/hour PER CALLER across every sandbox host, not per
# host. So a visitor who ran a few `curl` examples from the docs first can
# arrive here with nothing left, which is exactly what happened during the
# 2026-09-13 pre-launch audit.
AUTH=()
if [ -n "${SANDBOXAPIS_API_KEY:-}" ]; then
AUTH=(-H "Authorization: Bearer $SANDBOXAPIS_API_KEY")
fi
# What an over-limit refusal should say. The API's own 429 is correct and
# provider-shaped — Slack's is `{"ok":false,"error":"ratelimited"}` — but
# provider-shaped means it carries no upsell, so read literally it tells a
# newcomer only that something broke. Every other refusal in this product names
# the rung and the next one; this is the one a NEW visitor is likeliest to
# meet, so it says so here instead.
rate_limited() {
echo >&2
echo "${red}Rate-limited (HTTP $1).${off} This walk makes five requests, and anonymous" >&2
echo "access is 60 requests/hour per caller across every sandbox host — shared" >&2
echo "with any other example you have run in the last hour. Nothing is broken." >&2
echo >&2
echo " A free key raises it to 600/hour: ${bold}https://sandboxapis.dev/upgrade?from=anonymous${off}" >&2
echo " Then re-run with: ${bold}SANDBOXAPIS_API_KEY=sk_live_… pnpm demo${off}" >&2
echo >&2
echo "${dim} the API said: $(printf '%s' "$2" | tr -d '\n' | cut -c1-160)${off}" >&2
exit 1
}
# One GET. Sends the key when there is one, and turns an over-limit refusal
# into the message above rather than letting it reach `need` as an unreadable
# body. Everything else is still plain curl, so every URL printed above a hop
# remains something a reader can paste on its own.
get() {
local raw status
raw=$(curl -sS ${AUTH[@]+"${AUTH[@]}"} -w $'\n%{http_code}' "$1")
status=${raw##*$'\n'}
case "$status" in
403|429) rate_limited "$status" "${raw%$'\n'*}" ;;
esac
printf '%s' "${raw%$'\n'*}"
}
echo "${bold}One incident, four vendors' APIs.${off}"
echo "${dim}Every value below is read from a live response.${off}"
# --- 1. Slack: the conversation --------------------------------------------
URL="$SLACK/api/conversations.history?channel=$CHANNEL&limit=1"
hop "1 - Slack: the argument" "$URL"
SLACK_JSON=$(get "$URL")
TEXT=$(need "no message in #$CHANNEL" "$SLACK_JSON" "d['messages'][0]['text']")
TS=$(need "no timestamp on that message" "$SLACK_JSON" "d['messages'][0]['ts']")
SLACK_AT=$(TS="$TS" python3 -c "import datetime,os;print(datetime.datetime.utcfromtimestamp(float(os.environ['TS'])).strftime('%Y-%m-%dT%H:%M:%SZ'))")
ok "$SLACK_AT - \"$TEXT\""
# The distinctive phrase, taken from what Slack just said rather than typed
# here. Values reach python through the ENVIRONMENT, never spliced into its
# source: the opening message contains an apostrophe, and quoting user data
# into a program is fragile and the wrong habit besides.
PHRASE=$(TEXT="$TEXT" python3 -c "import os;print(os.environ['TEXT'].split('.')[0].strip())")
# --- 2. Jira: the same incident as a ticket ---------------------------------
URL="$JIRA/rest/api/3/issue/$KEY"
hop "2 - Jira: the ticket" "$URL"
JIRA_JSON=$(get "$URL")
SUMMARY=$(need "no such issue as $KEY" "$JIRA_JSON" "d['fields']['summary']")
CREATED=$(need "$KEY has no created date" "$JIRA_JSON" "d['fields']['created']")
ok "$KEY - \"$SUMMARY\""
PHRASE="$PHRASE" SUMMARY="$SUMMARY" python3 -c \
"import os,sys;sys.exit(0 if os.environ['PHRASE'].lower() in os.environ['SUMMARY'].lower() else 1)" \
|| fail "Slack's phrase is absent from Jira's summary - the two vendors disagree."
ok "Jira's summary carries Slack's exact words ${dim}(two vendors, one incident)${off}"
GAP=$(CREATED="$CREATED" TS="$TS" python3 -c "
import datetime, os
c = datetime.datetime.strptime(os.environ['CREATED'][:19], '%Y-%m-%dT%H:%M:%S')
s = datetime.datetime.utcfromtimestamp(float(os.environ['TS']))
print(int((s - c).total_seconds() // 60))
")
[ "$GAP" -gt 0 ] || fail "The thread opens before the ticket was filed - chronology is broken."
ok "Filed $GAP minutes before the thread opened ${dim}(chronology holds across vendors)${off}"
# --- 3. GitHub: the issue, DISCOVERED from Jira's words ---------------------
URL="$GH/repos/olympus-labs/parthenon/issues?state=all&per_page=100"
hop "3 - GitHub: the same issue, found using Jira's text" "$URL"
ISSUE_NUM=$(get "$URL" | SUMMARY="$SUMMARY" python3 -c "
import json, os, sys
want = os.environ['SUMMARY'].strip().lower()
for i in json.load(sys.stdin):
if i.get('title', '').strip().lower() == want:
print(i['number']); break
")
[ -n "$ISSUE_NUM" ] || fail "No GitHub issue carries Jira's summary."
ok "issue #$ISSUE_NUM - same title, discovered by searching on Jira's text"
# --- 4. GitHub: the pull request that fixed it ------------------------------
URL="$GH/repos/olympus-labs/parthenon/pulls/$PR"
hop "4 - GitHub: the pull request" "$URL"
PR_JSON=$(get "$URL")
BRANCH=$(need "no such pull request as #$PR" "$PR_JSON" "d['head']['ref']")
GH_SHA=$(need "PR #$PR has no head SHA" "$PR_JSON" "d['head']['sha']")
MERGED=$(need "PR #$PR has no merged flag" "$PR_JSON" "str(d['merged']).lower()")
[ "$MERGED" = "true" ] || fail "PR #$PR is not merged - the story does not close."
ok "PR #$PR merged ${bold}$BRANCH${off}"
ok "head SHA ${bold}$(printf '%.12s' "$GH_SHA")${off}"
# --- 5. GitLab: the same branch, DISCOVERED on another vendor ---------------
URL="$GL/api/v4/projects/olympus-labs%2Fparthenon/merge_requests?source_branch=$BRANCH"
hop "5 - GitLab: the same branch, on a different vendor" "$URL"
GL_JSON=$(get "$URL")
MR_IID=$(need "no GitLab MR for branch $BRANCH" "$GL_JSON" "d[0]['iid']")
GL_SHA=$(need "that MR has no head SHA" "$GL_JSON" "d[0]['sha']")
ok "MR !$MR_IID - found by the branch name GitHub just returned"
[ "$GH_SHA" = "$GL_SHA" ] || fail "SHAs differ: GitHub $GH_SHA vs GitLab $GL_SHA"
ok "head SHA $(printf '%.12s' "$GL_SHA") - ${green}identical to GitHub's${off}"
# --- what just happened ------------------------------------------------------
echo
echo "${bold}Four vendors. One story. No setup.${off}"
echo
echo " Slack the argument, at $SLACK_AT"
echo " Jira $KEY, filed $GAP minutes earlier"
echo " GitHub issue #$ISSUE_NUM, found using Jira's own words"
echo " GitHub PR #$PR merged $BRANCH"
echo " GitLab MR !$MR_IID - same branch, same SHA $(printf '%.12s' "$GH_SHA")"
echo
echo "Nothing was seeded by you, and the two cross-vendor hops were discovered,"
echo "not hardcoded: the GitHub issue was found using text Jira returned, and the"
echo "GitLab merge request was found using the branch GitHub returned."
echo
echo "Every host above is a frozen snapshot pinned to a content hash, so this"
echo "script returns these same bytes in a year. That is what CI needs and what"
echo "a live provider cannot give you."
echo
echo " ${dim}Point your own client at it:${off} https://sandboxapis.dev/docs"
echo " ${dim}What's covered, honestly:${off} https://sandboxapis.dev/coverage"
Needs only curl and python3, and python is used purely to read JSON — every request is a plain curl you can paste on its own.
What comes back
1 - Slack: the argument
ok 2026-06-14T16:46:48Z - "schema marks a nullable field as required. paging
whoever's closest to the logger."
2 - Jira: the ticket
ok FATE-46 - "Postmortem follow-up: schema marks a nullable field as required"
ok Jira's summary carries Slack's exact words (two vendors, one incident)
ok Filed 8 minutes before the thread opened (chronology holds across vendors)
3 - GitHub: the same issue, found using Jira's text
ok issue #46 - same title, discovered by searching on Jira's text
4 - GitHub: the pull request
ok PR #47 merged clio/leak-http-client-keep-alive-pool
ok head SHA d2aa02c65f19
5 - GitLab: the same branch, on a different vendor
ok MR !13 - found by the branch name GitHub just returned
ok head SHA d2aa02c65f19 - identical to GitHub'sThe walk
- Slackslack-2026-08.snapAn engineer opens a thread at 16:46:48Z — “schema marks a nullable field as required.”
- Jirajira-v3-g6.snapFATE-46 was filed eight minutes earlier, carrying that same sentence in its summary.
- GitHubgh-2026-03-g6.snapIssue #46 has the identical title — found by searching on the text Jira returned, not by a link.
- GitHubgh-2026-03-g6.snapPR #47 merged clio/leak-http-client-keep-alive-pool at d2aa02c65f19.
- GitLabgl-v4-g6.snapMR !13 — found by that branch name, on a different vendor, reporting the same SHA.
What this proves — and what it doesn't
Nothing here is hardcoded
Every value the script compares is read from a live response. Two of the hops are genuinely discovered rather than given: the GitHub issue is found by searching on the summary text Jira returned, and the GitLab merge request is found by the branch name GitHub returned. Change a value on one vendor and the script exits non-zero.
It is not a claim of hyperlinks
These providers don't cross-reference each other, any more than the real ones do. The claim is simpler: four vendors' APIs, asked independently, tell one coherent story — because it is one simulated company underneath, not four sets of fixtures someone kept in sync by hand.
It will say this in a year
Every host above is a frozen snapshot pinned to a content hash. Re-run this next year and the bytes are identical — which is what CI needs and what pointing your tests at a live provider can never give you. How pinning works.
Now point your own client at it
The same universe answers Octokit, python-gitlab, jira.js and the rest — the only change is the base URL. Nothing above required a key, and reads stay open without one. Start with the quickstart.