Documentation

API reference for developers · Base URL: https://api.braimsec.world

Scan code, read findings, and export results programmatically. Everything the dashboard does is available over a REST API authenticated with your API key.

Quickstart — no signup

You can try the full scan pipeline without an account using the trial API. It scans a public GitHub repository (shallow clone, 200 MB max) and returns a summary plus the top 5 findings.

1. Start a trial scan

curl -X POST https://api.braimsec.world/api/trial/scans \
  -H 'Content-Type: application/json' \
  -d '{"repo_url": "https://github.com/owner/repo"}'

# {"scan_id": "a1b2c3d4e5f6", "status": "queued",
#  "poll_url": "/api/trial/scans/a1b2c3d4e5f6"}

2. Poll for the summary

curl https://api.braimsec.world/api/trial/scans/a1b2c3d4e5f6

# {"scan_id": "a1b2c3d4e5f6", "status": "done",
#  "target": "github.com/owner/repo",
#  "severity_summary": {"error": 2, "warning": 5},
#  "total_findings": 7,
#  "top_findings": [
#    {"file": "app.py", "line": 12, "rule_id": "python.lang.security.audit",
#     "severity": "error", "message": "Possible SQL injection"}
#  ]}

Trial limits: 3 scans/hour and 3/day per IP (30/day total). Trial scans never consume plan quota. Prefer the web UI? Try it in your browser.

Authentication

All non-trial endpoints require your API key in the X-API-Key header. Your key is shown once when created — in the dashboard under API keys, or emailed to you after checkout. Never put the key in a URL.

curl -H 'X-API-Key: YOUR_API_KEY' https://api.braimsec.world/api/me

Exceeding your plan quota returns 402; a missing or invalid key returns 401.

Scanning your code

Submit a scan

POST /api/scans — multipart form. Upload a zip of your code:

curl -X POST https://api.braimsec.world/api/scans \
  -H 'X-API-Key: YOUR_API_KEY' \
  -F 'file=@myapp.zip'

# {"scan_id": "a1b2c3d4e5f6", "status": "queued"}
FieldTypeDescription
filefileZip archive of the code to scan.
project_idstringOptional. File the scan under one of your projects.
baseline_scan_idstringOptional. Incremental rescan against a previous scan's baseline (server-local paths only; zip uploads are always full scans).
webhook_urlstringOptional. We POST a signed JSON payload to this URL when the scan finishes. The signing secret is returned once in the response as webhook_secret.

Check status

GET /api/scans/{scan_id}

curl -H 'X-API-Key: YOUR_API_KEY' \
  https://api.braimsec.world/api/scans/a1b2c3d4e5f6

# {"id": "a1b2c3d4e5f6", "status": "done", "target_name": "myapp",
#  "total_findings": 7,
#  "severity_summary": {"error": 2, "warning": 3, "note": 2}}

Read findings

GET /api/scans/{scan_id}/results — full finding list (filter with ?severity=error). Each finding carries file, line, column, rule id, severity, message, the detecting tool, and the AI triage verdict.

curl -H 'X-API-Key: YOUR_API_KEY' \
  'https://api.braimsec.world/api/scans/a1b2c3d4e5f6/results?severity=error'

# [{"id": 42, "file": "app/db.py", "line": 87, "col": 12,
#   "rule_id": "braimsec-python-sqli", "tool": "semgrep",
#   "severity": "error", "triage_status": "open",
#   "message": "Possible SQL injection via string formatting",
#   "ai_verdict": null, "has_fix": false}]

Exports

EndpointFormatUse
GET /api/scans/{id}/sarifSARIF 2.1.0GitHub code scanning, CI gates
GET /api/scans/{id}/results.csvCSVSpreadsheets, custom tooling
GET /api/scans/{id}/report.pdfPDFHuman-readable reports
GET /api/scans/{id}/badge.svgSVGEmbeddable status badge for your README

CI integration — GitHub Actions

Gate pull requests on scan results. Store your key as a repository secret named BRAIMSEC_API_KEY:

name: BraimSec scan
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Zip the code
        run: zip -r code.zip . -x '.git/*'
      - name: Start scan
        run: |
          RESP=$(curl -s -X POST https://api.braimsec.world/api/scans \
            -H "X-API-Key: ${{ secrets.BRAIMSEC_API_KEY }}" \
            -F "file=@code.zip")
          SCAN_ID=$(echo "$RESP" | python3 -c "import json,sys; print(json.load(sys.stdin)['scan_id'])")
          echo "scan_id=$SCAN_ID" >> $GITHUB_ENV
      - name: Wait for completion
        run: |
          for i in $(seq 1 30); do
            STATUS=$(curl -s -H "X-API-Key: ${{ secrets.BRAIMSEC_API_KEY }}" \
              https://api.braimsec.world/api/scans/$scan_id \
              | python3 -c "import json,sys; print(json.load(sys.stdin)['status'])")
            echo "status: $STATUS"
            [ "$STATUS" = "done" ] && break
            sleep 20
          done
      - name: Export SARIF
        run: |
          curl -s -H "X-API-Key: ${{ secrets.BRAIMSEC_API_KEY }}" \
            https://api.braimsec.world/api/scans/$scan_id/sarif -o braimsec.sarif
      - name: Upload to GitHub code scanning
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: braimsec.sarif

GitHub pull request comments

When a pull request targets your watched branch, BraimSec scans the PR head commit and posts the result as a comment on the PR thread — the same comment is updated on every new push to the PR, so the thread never gets spammed. Setup:

  1. Create a fine-grained personal access token with Pull requests: read and write on the repository.
  2. Pass it as github_token when registering the repo (POST /api/vcs/repos) or later via PATCH /api/vcs/repos/{repo_id}. The token is write-only: it is stored encrypted and never returned by the API — responses carry a pr_comments_enabled flag instead.
  3. In your GitHub webhook settings, enable the Pull requests event alongside pushes.

The comment shows the finding count by severity and the top 10 findings (file:line — severity — rule), reports a clean scan when there is nothing to flag, and says so loudly when the scan itself fails. The token is used only to post comments — cloning still uses the public repository URL, and forked PR heads are cloned read-only from the fork's public URL.

Webhooks

Pass webhook_url when creating a scan and we will POST a signed JSON payload to it when the scan reaches a terminal state. Verify it with the X-BraimSec-Signature: sha256=… header using the webhook_secret returned at creation. You can also rotate the signing secret anytime via POST /api/webhook-signing/rotate.

Account endpoints

EndpointDescription
GET /api/plansAvailable plans and quotas (public, no key needed)
GET /api/subscriptionYour current plan and status
GET /api/usageScan and AI-review usage this period
GET /api/projects · POST /api/projectsManage projects
GET /api/keys · POST /api/keysManage API keys (keys are shown once at creation)
GET /api/audit-logAccount audit trail (CSV export available)

Rate limits & errors

CodeMeaning
401Invalid or missing X-API-Key header
402Monthly scan quota exceeded — upgrade your plan
404Scan or resource not found
429Rate limit exceeded — back off and retry
503Scan queue temporarily unavailable — retry shortly

Need help?

Email support@braimsec.world — a human replies. For interactive API exploration, the live OpenAPI browser is at api.braimsec.world/docs.