API Reference¶
REST API for CI/CD code reviews. Base URL: https://api.bedefended.com
Authentication¶
All CI/CD endpoints require an API key via the X-BD-API-Key header:
POST /api/v1/ci/review HTTP/1.1
Host: api.bedefended.com
X-BD-API-Key: bd_sk_abc123def456...
Content-Type: application/json
API keys are created by BeDefended staff via the admin dashboard. Each key is:
- Bound to a company
- Scoped to a repo pattern (e.g.,
org/repoororg/*) - Assigned a tier (essentials, professional, enterprise)
- Rate-limited by monthly scan count
Endpoints¶
POST /api/v1/ci/review¶
Submit SAST results for code review.
Request:
{
"repo_url": "https://github.com/acme/webapp",
"commit_sha": "abc123def456",
"pr_number": 42,
"branch": "feature/login",
"diff_files": [
{
"path": "app/views/auth.py",
"status": "modified",
"additions": 15,
"deletions": 3
}
],
"sast_results": [
{
"tool": "semgrep",
"rule_id": "python.sqli",
"severity": "high",
"message": "SQL Injection detected",
"file": "app/views/auth.py",
"line_start": 42,
"metadata": {"cwe": {"id": "89"}}
}
],
"config": {}
}
Response (201):
{
"review_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "complete",
"findings": [
{
"id": "CR-FINDING-001",
"vuln_type": "python.sqli",
"title": "SQL Injection detected",
"severity": "high",
"confidence": "possible",
"description": "SQL Injection detected",
"location": {
"file": "app/views/auth.py",
"line_start": 42
},
"source_tool": "semgrep",
"ai_enriched": false
}
],
"summary": {
"total_findings": 1,
"critical_count": 0,
"high_count": 1,
"medium_count": 0,
"low_count": 0,
"info_count": 0,
"files_reviewed": 1
},
"quality_gate": "fail"
}
Status values:
| Status | Meaning |
|---|---|
pending |
Review received, queued |
sast_complete |
SAST normalization done |
ai_analyzing |
AI analysis in progress (Professional+) |
complete |
Analysis finished |
failed |
Processing error |
For Professional/Enterprise tiers, status may be ai_analyzing. Poll via GET until complete.
GET /api/v1/ci/review/{review_id}¶
Poll for review completion.
Response (200): Same schema as POST response.
GET /api/v1/ci/review/{review_id}/sarif¶
Get SARIF 2.1.0 output for a completed review.
Response (200): SARIF 2.1.0 JSON document.
Error (409): Review not yet complete.
POST /api/v1/ci/api-keys¶
Create a new API key. Requires admin JWT authentication.
Request:
Response (201):
{
"api_key": "bd_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"key_prefix": "bd_sk_a1b2c3...",
"tier": "professional",
"repo_pattern": "acme/*",
"monthly_scan_limit": 2000
}
Store Securely
The full API key is only shown once at creation time. Store it immediately in your CI/CD secrets. BeDefended only stores the SHA-256 hash.
GET /api/v1/ci/usage/{company_id}¶
Get CI/CD usage metrics. Requires staff JWT authentication.
Response (200):
{
"company_id": 1,
"scans_this_month": 127,
"total_findings": 342,
"by_severity": {
"critical": 5,
"high": 28,
"medium": 134,
"low": 175
},
"plan": "Code Review Professional"
}
Error Responses¶
| Code | Meaning |
|---|---|
| 401 | Invalid or missing API key |
| 403 | Admin access required |
| 404 | Review or company not found |
| 409 | Review not yet complete (for SARIF endpoint) |
| 429 | Monthly scan limit exceeded |
All errors return:
Rate Limits¶
| Limit | Scope |
|---|---|
| Monthly scans | Per API key (configured by plan) |
| Request rate | Per IP via slowapi |
| AI timeout | 3 minutes per review (Professional+) |