Quickstart: score a message from CI
Three steps. Create a test to get an address, send your real message to it, then poll for the score.
Your key needs both scopes: tests:write to create the test and tests:read to read the
result back.
1. Create a test
curl -s -X POST https://api.deliversight.com/v1/tests
-H "Authorization: Bearer $DELIVERSIGHT_API_KEY" {
"token": "ds-q6mdtt6rqbktzg74",
"address": "[email protected]",
"source": "api",
"expires_at": "2026-08-03T05:46:54.406186979Z",
"created_at": "2026-07-27T05:46:54.403576Z"
} The address is single-use and expires — allocate a fresh one for each run rather than reusing it.
2. Send your message to that address
Send the real message you want judged, through the real sending path you want judged — your production ESP, your own MTA, whatever ships to customers. That is the whole point: the score reflects the message and the route it took, so a message sent from your laptop tells you about your laptop.
3. Poll for the score
Use GET /v1/tests/{token} with your key. Scoring starts when the message arrives and takes a
few seconds; status is pending until then.
curl -s https://api.deliversight.com/v1/tests/ds-q6mdtt6rqbktzg74
-H "Authorization: Bearer $DELIVERSIGHT_API_KEY" {
"token": "ds-q6mdtt6rqbktzg74",
"address": "[email protected]",
"status": "scored",
"score": 9,
"max_score": 10,
"gated": false,
"checks": [
{
"name": "content",
"status": "failed",
"score": -1,
"detail": { "list_unsubscribe": "missing List-Unsubscribe header" }
},
{
"name": "dkim",
"status": "passed",
"score": 0,
"detail": { "valid_domains": "mail.example.com" }
}
]
} score counts down from max_score: every check that fails subtracts, and each one tells you
what it subtracted and why. A passing check contributes 0.
Do not use GET /v1/shared/{token} for a test you created with a key. That endpoint takes no
credential, so it deliberately serves only the anonymous tests created on the website — an
API-created test returns 404 there, however valid the token. A key-created address transits your
ESP and can leak from a bounce or a log, so its results are never readable without your key.
The whole thing
#!/usr/bin/env bash
set -euo pipefail
API="https://api.deliversight.com"
AUTH="Authorization: Bearer ${DELIVERSIGHT_API_KEY:?set DELIVERSIGHT_API_KEY}"
MIN_SCORE="${MIN_SCORE:-8}"
# 1. Allocate an address.
read -r TOKEN ADDRESS < <(
curl -sf -X POST "$API/v1/tests" -H "$AUTH" |
python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["token"], d["address"])'
)
echo "test $TOKEN -> $ADDRESS"
# 2. Send the message you actually ship, however you actually ship it.
./send-release-notes.sh "$ADDRESS"
# 3. Poll until scored, with your key. Give up rather than loop forever: mail can
# be delayed or silently dropped, and a CI job that hangs is worse than one
# that fails.
for _ in $(seq 1 60); do
REPORT=$(curl -sf "$API/v1/tests/$TOKEN" -H "$AUTH")
STATUS=$(printf '%s' "$REPORT" | python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])')
[ "$STATUS" = "scored" ] && break
sleep 5
done
if [ "$STATUS" != "scored" ]; then
echo "message never arrived (status: $STATUS)" >&2
exit 1
fi
printf '%s' "$REPORT" | MIN="$MIN_SCORE" python3 -c '
import json, os, sys
r = json.load(sys.stdin)
print(f"score {r["score"]}/{r["max_score"]}")
for c in r.get("checks", []):
if c["status"] != "passed":
print(f" {c["name"]}: {c["score"]} {c.get("detail", {})}")
if r["score"] < float(os.environ["MIN"]):
sys.exit("below threshold")
'
echo "ok" Poll politely
Scoring takes seconds, not milliseconds. Poll every few seconds, cap your attempts, and respect Retry-After if you are rate limited — see Rate limits and errors.
Better still, do not poll at all: subscribe to the test.scored webhook and let
us tell you.