Auth: JWT vs API key
Every request needs an Authorization: Bearer <token> header. Two kinds of token:
| Cognito JWT | API key | |
|---|---|---|
| Lifetime | ~60 min | Until revoked |
| Best for | Interactive use, CLI scripts you run by hand | CI, cron, backend services, automation |
| How to get one | Dashboard → profile → CLI access → Copy access token | Dashboard → profile → API keys → + New key |
| Tier required | Any (Watcher included) | Analyst+ (Watcher returns 403) |
| Header | Authorization: Bearer <token-or-key> | |
Quotas & rate-limits
Two limits, both enforced atomically:
- Per-day lookups on
/v1/objects/{norad_id}: 10 / 5,000 / 50,000 / 1,000,000 (Watcher / Analyst / Operator / Mission). Resets at 00:00 UTC. Over-quota respondsHTTP 429withretry_after_seconds. - Per-minute RPM across all endpoints: n/a / 60 / 300 / 1,500. Over-RPM also responds
HTTP 429.
Check your live quota:
curl -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/usage/today
GET /v1/objects/{norad_id}
Catalog lookup for a single NORAD ID. Costs one lookup against your daily quota.
curl -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/objects/25544
Response (Analyst+):
{
"schema": "debrisguard.public.object_lookup.v2",
"norad_cat_id": "25544",
"available": true,
"enrichment": {
"name": "ISS (ZARYA)",
"orbit_class": "LEO",
"epoch": "2026-05-18T12:14:08Z",
"subpoint_lat": -22.4,
"subpoint_lon": 145.7,
"subpoint_alt_km": 433.0,
"detectors_active": ["bstar_drift","catalog","manoeuvre"],
"bstar_drift": {
"score": 0.04, "z_score": 0.3, "trend_14d": "stable",
"decay_roster": false
},
"manoeuvre": {
"detected_in_window_d": 14,
"last_burn_epoch": "2026-05-12T01:03:00Z",
"advice_chip": "monitor",
"advice_confidence": 0.51
},
"catalog_detector": {
"d_squared": 0.0021, "outlier": false
}
},
"score": { "fused_score": 0.18, "severity": "info", "is_alert": false }
}
Watcher tier: identical enrichment.name / orbit_class / subpoint_* but bstar_drift, manoeuvre, and catalog_detector blocks are omitted.
GET /v1/reports/daily/latest
Today's anomaly report. Free for all tiers; historical dates (/v1/reports/daily/2026-05-12) are Analyst+ only.
curl -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/reports/daily/latest
Response:
{
"schema": "debrisguard.public.daily_report.v2",
"report_date": "2026-05-19",
"alerts_total": 8,
"pipeline_coverage": {
"tracked_objects": 27411,
"scored_objects": 27411,
"manoeuvre_window_d": 14,
"burns_detected_14d": 1667,
"burn_confirmation_rate": 0.745,
"decay_roster_size": 63
},
"top_objects": [
{ "norad_cat_id":"58712","name":"STARLINK-32115",
"fused_score":0.71,"detectors":["manoeuvre","catalog"] },
…
]
}
GET /v1/manoeuvres/recent
Pipeline-wide manoeuvre detections from the rolling 14-day window. Analyst+ only. Watcher → HTTP 403.
curl -H "Authorization: Bearer $DG_TOKEN" \
'https://api.debrisguard.deepfieldlabs.dev/v1/manoeuvres/recent?limit=20'
Query params: limit (default 25, max 100), chip=escalate|review|monitor, kind=thrust_event_detected|manoeuvre_or_orbit_drift, watchlist=1 (your watchlist only).
Response:
{
"schema": "debrisguard.public.manoeuvres_recent.v1",
"window_days": 14,
"n_objects_with_burns": 1213,
"chip_legend": {
"escalate": "High confidence AND (watchlisted OR active CDM)",
"review": "High confidence, or medium confidence with priority",
"monitor": "Lower confidence or single-pair detection"
},
"items": [
{ "norad_cat_id":"58712","name":"STARLINK-32115",
"last_burn_epoch":"2026-05-18T02:11:00Z",
"advice_confidence":0.94,"advice_chip":"escalate",
"n_pairs":3,"watchlisted":true }
]
}
/v1/fleet — watchlist
# list your watchlist
curl -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/fleet
# pin a NORAD
curl -X POST -H "Authorization: Bearer $DG_TOKEN" \
-H "Content-Type: application/json" \
-d '{"norad_cat_id":"25544"}' \
https://api.debrisguard.deepfieldlabs.dev/v1/fleet
# unpin
curl -X DELETE -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/fleet/25544
Exceeding the tier cap returns:
HTTP/1.1 409 Conflict
{"error":"tier 'analyst' allows up to 5 watchlist items (currently 5)"}
GET /v1/usage/today
{
"schema": "debrisguard.public.usage_today.v1",
"tier": "analyst",
"catalog_lookups_today": 42,
"catalog_lookups_limit": 5000,
"watchlist_size": 3,
"watchlist_limit": 5,
"api_keys_active": 2
}
/v1/webhooks (Operator+)
Subscribe a Slack / Teams / generic webhook to new alerts. Watcher and Analyst → HTTP 403.
# create
curl -X POST -H "Authorization: Bearer $DG_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.slack.com/...","kind":"slack",
"filter":{"min_severity":"alert"}}' \
https://api.debrisguard.deepfieldlabs.dev/v1/webhooks
# list
curl -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/webhooks
# delete
curl -X DELETE -H "Authorization: Bearer $DG_TOKEN" \
https://api.debrisguard.deepfieldlabs.dev/v1/webhooks/<id>
Delivery is retried with exponential backoff (1 s → 16 s, 5 attempts) then dead-lettered to SQS for replay via the /v1/webhooks/<id>/replay endpoint.
Common error responses
| Status | Meaning | What to do |
|---|---|---|
401 | Missing / expired JWT | Refresh your access token or use an API key. |
403 | Tier doesn't allow this endpoint | Upgrade tier, or check that you're not on Watcher for a paid-only endpoint. |
404 | NORAD not in the active catalog | Try a different ID, or check that the object hasn't decayed. |
409 | Watchlist full | Remove a pinned NORAD or upgrade tier. |
429 | Quota exhausted (day or minute) | Read retry_after_seconds; back off; upgrade if persistent. |
5xx | Server error | Read x-correlation-id, include it in a support ticket. |
Full integration examples
Python — daily decay-roster digest
import os, requests
TOK = os.environ["DG_TOKEN"] # API key
BASE = "https://api.debrisguard.deepfieldlabs.dev"
HEAD = {"Authorization": f"Bearer {TOK}"}
report = requests.get(f"{BASE}/v1/reports/daily/latest", headers=HEAD).json()
roster = [o for o in report["top_objects"] if "bstar-drift" in o["detectors"]]
print(f"Re-entry candidates today: {len(roster)}")
for o in roster:
print(f" {o['norad_cat_id']:>6} {o['name']:<25} {o['fused_score']:.2f}")
Bash — watch a NORAD and ping you on burn detection
NORAD=25544
res=$(curl -sS -H "Authorization: Bearer $DG_TOKEN" \
"https://api.debrisguard.deepfieldlabs.dev/v1/objects/$NORAD")
chip=$(echo "$res" | jq -r '.enrichment.manoeuvre.advice_chip // "none"')
[[ "$chip" == "escalate" ]] && \
curl -s -X POST -d "{\"text\":\"BURN ESCALATE on $NORAD\"}" \
"$SLACK_WEBHOOK_URL"
DeepField Labs · DebrisGuard guide