Browse documentation
bbradar Pro guide

Pro API reference

Complete reference for authentication, platform and Self-Hosted data, MCP-efficient polling, endpoints, examples, responses, limits, and errors.

15 min readReviewed Read as Markdown
On this page

Authentication

v1

Every Pro API request uses your personal API key as a Bearer token. Keep the key in a server-side secret or MCP client environment—never in browser JavaScript or a public repository.

Base URL

https://bbradar.io/api

Request header

Authorization: Bearer YOUR_PRO_API_KEY

The complete secret is displayed once. Regenerating it immediately invalidates the previous key.

Manage API key

Make your first request

Start with capabilities so automation can negotiate the current contract without scanning catalog data.

curl -sS "https://bbradar.io/api/v1/pro/capabilities" -H "Authorization: Bearer YOUR_PRO_API_KEY"
Invalid query or path parameters return 400 with a detail message and an errors array. Authentication failures return 401; missing programs return 404.

Catalog status and field types

Program lists and exact detail include confirmed paused platform programs. Read program_status and is_active together: a paused program retains is_active: false. Its scope and reward information describe the last published state, and bounty eligibility is disabled. Global target search, opportunity lists, and change feeds require active programs. Exact target reads may return retained scope with the parent status attached; bulk exports include paused scope only with explicit program IDs and include_ineligible=true.

Field
program_status / is_active
Type and meaning
String status and boolean lifecycle state. Paused platform metadata remains visible; paused does not mean active.
Field
star_rating
Type and meaning
Integer from 1 to 5, or null when the vote threshold is not met.
Field
review_signal / weighted_sentiment
Type and meaning
Numbers derived from recorded vote totals; these are not text review labels.
Field
report_count
Type and meaning
Number or null. Check report_count_source and report_count_label when present because platform reporting windows differ.
Field
submission_cost
Type and meaning
Object or null. Missing platform observations currently default to amount 0 with source missing_defaults_free; free-platform policy uses platform_policy. Neither default is a newly observed fee.
Field
data_capabilities
Type and meaning
Boolean markers for available catalog signals. A false capability means unsupported, not a measured zero.

Examples use fictional programs and reserved example domains. Response examples are abbreviated; preserve unknown fields for forward compatibility. Identifiers use the exact platform:handle returned by the API, and handles can contain slashes.

Opportunity and Target Intelligence

Pro responses include structured signals that clients can display directly. Each field below has one job.

Program opportunity

opportunity_tag
Tier, score, factors, and the reason a program is highlighted.
submission_cost
Amount, optional maximum, unit, fee or deposit type, source, and observation time.

Target score

targetOpportunityScoretargetOpportunityLabel
A 0–100 score and its fixed Elite, Strong, Potential, or Normal label.
targetScoreBreakdownwhyThisTarget
The underlying factors and a concise human-readable explanation.

Competition risk

competitionRiskcompetitionRiskReason
Low, Medium, High, or Unknown, plus the evidence behind that classification.
Higher means more crowded or duplicate-prone. Unknown means insufficient public data—not Low risk.

Self-Hosted capability markers

Self-Hosted IDs use Self-Hosted:program-slug. Their data_capabilities object is authoritative: target inventory is returned, while report counts, opportunity scores, target-change history, submission costs, and repository changes are not invented when no source exists.

Target labels use fixed score bands: Elite Target is 85–100, Strong Target is 70–84, Potential Target is 50–69, and Normal is 0–49. Out-of-scope or explicitly ineligible targets do not receive Target Intelligence.

Use scoring model versions and evidence coverage in the returned breakdowns to interpret the available factors. Scores and competition labels are comparative estimates, not measured duplicate probabilities. Repository events include a comparison object describing evidence completeness, method, reason, matcher version, ancestry, and provider commit count when known. Target associations expose match_quality and match_reason; program summaries preserve match_qualities, including when include_targets=false. Unknown evidence remains unknown.

Efficient MCP polling

Use after_id for incremental feeds. Results are oldest-first; start with after_id=0, persist meta.next_after_id after processing the response, and send it with the next request. This skips total-count and facet work.

Target changes

curl -sS -G "https://bbradar.io/api/v1/pro/targets/changes" \
  --data-urlencode "after_id=48101" \
  --data-urlencode "page_size=50" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Repository summaries

curl -sS -G "https://bbradar.io/api/v1/pro/repositories/changes" \
  --data-urlencode "after_id=17041" \
  --data-urlencode "include_targets=false" \
  --data-urlencode "page_size=50" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Cursor mode requires page=1. Repository target-intelligence filters are page-only; indexed search, platform, tag, submission-cost, and visibility filters can be used with the cursor.

Stable pages and recovery

Ordinary page requests read live data. For stable pagination, send snapshot=start on page 1 of programs, target search, target changes, or repository changes. Reuse meta.snapshot on later pages with the same filters and account. Page size may change. Use meta.snapshot_expires_at and meta.as_of to track expiry and the observation cutoff.

Snapshot response metadata (illustrative)
{
  "meta": {
    "snapshot": "EXAMPLE_TOKEN_RETURNED_BY_THE_API",
    "snapshot_expires_at": "2026-09-07T12:05:00Z",
    "as_of": "2026-09-07T12:00:00Z",
    "consistency": "snapshot",
    "page": 1,
    "page_size": 50,
    "has_more": true
  }
}

Snapshots last five minutes and hold at most 5,000 rows and 64 MiB of JSON, stored compressed within 4 MiB. At most three snapshots per account and sixteen globally can be active. Narrow filters after 413; honor Retry-After when capacity returns 429 or a snapshot read runs out of time with 503. A 410 requires a new snapshot on page 1. If a snapshot includes a change cursor, finish every snapshot page before advancing the cursor.

Change feeds contain retained observations, and target changes represent the latest material state per target. They are not an immutable event journal. Reconcile current inventory periodically and after disconnection; a cursor older than retained history returns 410 and requires resynchronization. Exports use a consistent read, return at most 500 targets, and report truncation in metadata.

MCP 0.2.3 exposes both change feeds and cursor polling. Its published tool schemas do not expose snapshot tokens; use the HTTP API when stable pages are required.

Activity, payouts and derived signals

Read available views before requesting a ranking. These Pro routes use the same frozen calculations and explanations as the website. Keep nulls, bounds, source definitions and observation times intact. An observed increase does not identify an individual payment.

GET route
/api/v1/pro/activity/capabilities
Contract
Available tabs, period/basis/precision combinations, sorts, directions and label filters.
GET route
/api/v1/pro/activity/rankings
Contract
One sortable page (limit 1–100) with meta.as_of, snapshot_id and next_cursor. Tabs: payouts, value, scope, rewards, updates, reports, response, status, all_changes.
GET route
/api/v1/pro/payouts/programs/{program_id}
Contract
Exact program facts, signals, labels, label_details and same-platform value_points. Handles may contain slashes.
GET route
/api/v1/pro/activity/events/{change_id}
Contract
Lazy before/after details; supply the originating ranking’s meta.snapshot_id as snapshot.

Value uses lifetime payout per processed report and 90-day received volume, so omit period. It returns all matching map points (up to 5,000) separately from paginated rows. Platform percentiles are frozen before filters; label-specific shortlists may include programs without both map inputs. Use the advertised sort and direction and keep every filter unchanged with the cursor. A 410 requires a fresh query; a 422 means the requested view is unavailable or the selection must be narrowed. Private responses are no-store.

Example Value query
curl -sS "https://bbradar.io/api/v1/pro/activity/rankings?tab=value&labels=pays_near_top_reward&sort=realization&direction=desc&limit=25" -H "Authorization: Bearer YOUR_PRO_API_KEY"

Endpoint reference

Each endpoint includes its purpose, parameters, cURL request, and an abbreviated response. Use the endpoint links to jump directly to a section.

Negotiate the authenticated v1 contract, supported catalogs, route methods, filters, and hard result limits without querying catalog data.

Parameters and examples

Parameters

No query parameters

Bearer authentication is required

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/capabilities" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "api_version": "v1",
  "contract_version": "2026-09-06",
  "behavior": {
    "read_only": true,
    "private_cache_control": "no-store",
    "catalogs": ["platform", "self_hosted"],
    "scoring_version": 3,
    "submission_cost_policy_version": 1,
    "stable_snapshots": {
      "endpoints": ["programs", "target_search", "target_changes", "repository_changes"],
      "parameter": "snapshot", "start_value": "start", "ttl_seconds": 300,
      "max_rows": 5000, "max_bytes": 67108864, "max_decoded_bytes": 67108864,
      "max_stored_bytes": 4194304, "storage": "compressed", "expired_status": 410
    },
    "change_feed_contract": "latest retained state; reconcile inventory periodically; not an immutable event journal"
  },
  "endpoints": {
    "programs": { "method": "GET", "max_page_size": 100, "self_hosted": true },
    "program_detail": { "method": "GET", "self_hosted": true, "path_handles_may_contain_slashes": true },
    "program_targets": { "method": "GET", "max_page_size": 500, "self_hosted": true },
    "target_search": { "method": "GET", "max_page_size": 500, "self_hosted": true },
    "target_export": { "method": "POST", "max_targets": 500, "max_program_ids": 50, "max_request_body_bytes": 65536 },
    "target_changes": { "method": "GET", "max_page_size": 100, "self_hosted": false, "incremental_cursor": { "parameter": "after_id", "order": "ascending", "max_scan_rows": 2000, "returns_facets": false } },
    "repository_changes": { "method": "GET", "max_page_size": 100, "self_hosted": false, "includes_code_or_diff_content": false, "returns_facets": false, "max_association_rows_per_request": 5000, "incremental_cursor": { "parameter": "after_id", "order": "ascending", "skips_total_count": true }, "optional_summary_mode": { "parameter": "include_targets", "value": false, "returns_affected_programs": true } },
    "opportunities": { "method": "GET", "max_page_size": 100, "self_hosted": false }
  }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

List active and confirmed paused platform programs, plus active Self-Hosted programs, with server-side search, filters, and pagination.

Parameters and examples

Parameters

platforms (csv, optional)

Use platforms=Self-Hosted for only the Self-Hosted catalog

tags (csv, optional; scope, language, or target-type tags)

search (optional; name, handle, platform, policy host, or Self-Hosted target)

updated_since (ISO datetime, optional)

snapshot (optional; start on page 1, then reuse meta.snapshot with the same filters/account; expires after 5 minutes)

page (default: 1)

page_size (max: 100)

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/programs" \
  -G \
  --data-urlencode "page=1" \
  --data-urlencode "page_size=20" \
  --data-urlencode "search=example" \
  --data-urlencode "platforms=hackerone,bugcrowd,Self-Hosted" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "programs": [
    {
      "id": "HackenProof:example-handle",
      "handle": "example-handle",
      "name": "Example Program",
      "platform": "HackenProof",
      "link": "https://hackenproof.com/programs/example-handle",
      "profile_picture": "https://example.com/logo.png",
      "scope_tags": ["domain", "api"],
      "added_at": "2026-03-04T12:10:00Z",
      "date_launched": "2026-03-04",
      "last_updated": "2026-04-16T07:45:02Z",
      "targets_updated_at": "2026-04-16T07:45:02Z",
      "bounty_min": 100,
      "bounty_max": 5000,
      "report_count": 353,
      "submission_cost": {
        "amount": 5,
        "unit": "USD",
        "kind": "fee",
        "source": "hackenproof_catalog",
        "updated_at": "2026-04-16T07:45:02Z"
      },
      "up_votes": 48,
      "down_votes": 3,
      "total_votes": 51,
      "net_score": 45,
      "vote_ratio": 0.9412,
      "star_rating": 5,
      "review_signal": 3.9512437185814275,
      "weighted_sentiment": 19.756218592907137,
      "competitionRisk": "Medium",
      "competitionRiskReason": "Estimated from high public report count, less obvious asset type.",
      "target_counts": {
        "total": 42,
        "in_scope": 38,
        "out_of_scope": 4,
        "eligible_for_bounty": 32,
        "wildcard": 7
      },
      "target_activity": {
        "latest_change_at": "2026-04-16T07:45:02Z",
        "latest_added_at": "2026-04-15T09:20:31Z",
        "added_24h": 3,
        "added_7d": 9,
        "removed_7d": 1
      },
      "extra_data": {
        "report_count": 353,
        "report_count_source": "reports_received_last_90_days",
        "report_count_label": "reports received (last 90 days)"
      }
    }
  ],
  "meta": { "page": 1, "page_size": 20, "total": 120, "total_pages": 6 }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

Fetch one exact platform or Self-Hosted program without scanning list pages.

Parameters and examples

Parameters

program_id (required path param)

program_id format: platform:handle

Self-Hosted example: Self-Hosted:example-security

Handles containing "/" are supported

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/programs/Self-Hosted:example-security" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "id": "Self-Hosted:example-security",
  "handle": "example-security",
  "name": "Example Security",
  "platform": "Self-Hosted",
  "catalog": "self_hosted",
  "link": "https://example.com/security",
  "policy_url": "https://example.com/security",
  "policy_host": "example.com",
  "program_type": "paid",
  "reward_status": "paid",
  "reward_currency": "USD",
  "reward_types": ["cash"],
  "reporting_email": "[email protected]",
  "reporting_url": "https://example.com/report",
  "safe_harbor": "full",
  "verified_at": "2026-08-25T09:00:00Z",
  "scope_tags": ["api", "web"],
  "bounty_min": 100,
  "bounty_max": 5000,
  "report_count": null,
  "submission_cost": null,
  "date_launched": null,
  "data_capabilities": {
    "target_inventory": true,
    "target_changes": false,
    "opportunity_scoring": false,
    "public_report_count": false,
    "submission_cost": false,
    "repository_changes": false
  },
  "target_counts": {
    "total": 8,
    "in_scope": 7,
    "out_of_scope": 1,
    "eligible_for_bounty": 7,
    "wildcard": 2
  }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

List scored platform programs matching one opportunity tier. Self-Hosted rows are excluded because no opportunity score is fabricated.

Parameters and examples

Parameters

level (required path param: elite|hot|strong|potential)

platforms (csv, optional)

tags (csv, optional; scope, language, or target-type tags)

search (optional; name, handle, or platform)

updated_since (ISO datetime, optional)

page (default: 1)

page_size (max: 100)

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/opportunities/elite" \
  -G \
  --data-urlencode "page=1" \
  --data-urlencode "page_size=20" \
  --data-urlencode "platforms=hackerone,bugcrowd" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "programs": [
    {
      "id": "YesWeHack:example-handle",
      "handle": "example-handle",
      "name": "Example Program",
      "platform": "YesWeHack",
      "link": "https://yeswehack.com/programs/example-handle",
      "profile_picture": "https://example.com/logo.png",
      "scope_tags": ["domain", "api"],
      "added_at": "2026-04-10T12:10:00Z",
      "date_launched": "2026-04-10",
      "last_updated": "2026-04-16T07:45:02Z",
      "targets_updated_at": "2026-04-16T07:45:02Z",
      "bounty_min": 100,
      "bounty_max": 10000,
      "report_count": 1,
      "submission_cost": {
        "amount": 3,
        "unit": "credits",
        "kind": "fee",
        "source": "yeswehack_programs_api",
        "updated_at": "2026-04-16T07:45:02Z"
      },
      "up_votes": 48,
      "down_votes": 3,
      "total_votes": 51,
      "net_score": 45,
      "vote_ratio": 0.9412,
      "star_rating": 5,
      "review_signal": 3.9512437185814275,
      "weighted_sentiment": 19.756218592907137,
      "competitionRisk": "Low",
      "competitionRiskReason": "Estimated from very low public report count, less obvious asset type.",
      "target_counts": {
        "total": 42,
        "in_scope": 38,
        "out_of_scope": 4,
        "eligible_for_bounty": 32,
        "wildcard": 7
      },
      "target_activity": {
        "latest_change_at": "2026-04-16T07:45:02Z",
        "latest_added_at": "2026-04-15T09:20:31Z",
        "added_24h": 3,
        "added_7d": 9,
        "removed_7d": 1
      },
      "extra_data": {
        "report_count": 1,
        "report_count_source": "reports_received_last_90_days",
        "report_count_label": "reports received (last 90 days)"
      },
      "opportunity_tag": {
        "tier": "elite",
        "label": "Elite",
        "description": "Very fresh, lightly reported, and strong payout potential.",
        "reason": "Added 6 days ago • 1 public report • Up to $10,000 bounty",
        "opportunity_score": 97.5,
        "freshness": 100,
        "competition": 100,
        "reward": 90,
        "scope_bonus": 0,
        "signal_count": 3,
        "is_vdp": false
      }
    }
  ],
  "meta": {
    "level": "elite",
    "page": 1,
    "page_size": 20,
    "total": 8,
    "total_pages": 1
  }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

Fetch retained active target rows for one platform or Self-Hosted program. Paused parent status is included and bounty eligibility is disabled while paused; Target Intelligence appears only when supported.

Parameters and examples

Parameters

program_id (required path param)

program_id format: platform:handle

Handles can include "/" and are supported in this path

Example: BugCrowd:engagements/example-program

Self-Hosted example: Self-Hosted:example-security

eligibility (all|eligible|ineligible, optional)

target_type (optional)

search (optional; target identifier or display name)

minTargetScore (0-100, optional)

targetOpportunityLabel (Elite Target|Strong Target|Potential Target|Normal, optional)

competitionRisk (Low|Medium|High|Unknown, optional)

page (default: 1)

page_size (default: 250, max: 500)

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/programs/BugCrowd:engagements/example-program/targets" \
  -G \
  --data-urlencode "eligibility=eligible" \
  --data-urlencode "target_type=domain" \
  --data-urlencode "search=api" \
  --data-urlencode "minTargetScore=70" \
  --data-urlencode "targetOpportunityLabel=Strong Target" \
  --data-urlencode "competitionRisk=Low" \
  --data-urlencode "page=1" \
  --data-urlencode "page_size=250" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "targets": [
    {
      "target_type": "domain",
      "identifier": "*.example.com",
      "display_name": "*.example.com",
      "normalized_identifier": "example.com",
      "scope_tags": ["domain", "api"],
      "language_tags": ["javascript"],
      "in_scope": true,
      "eligible_for_bounty": true,
      "severity_score": 8.2,
      "severity_label": "High",
      "metadata": {},
      "source_url": "https://example.com/policy",
      "added_at": "2026-04-15T09:20:31Z",
      "source_added_at": "2026-04-14",
      "last_seen": "2026-04-16T07:45:02Z",
      "last_change_type": "added",
      "last_changed_at": "2026-04-15T09:20:31Z",
      "is_active": true,
      "wildcard": true,
      "targetOpportunityScore": 84,
      "targetOpportunityLabel": "Strong Target",
      "targetScoreBreakdown": {
        "freshness": { "score": 25, "label": "Last 7 days", "days": 3.1 },
        "targetType": { "score": 22, "label": "Wildcard", "key": "wildcard" },
        "reward": { "score": 22, "label": "High bounty", "maxBounty": 10000, "isNoReward": false },
        "reportActivity": { "score": 15, "label": "Very low public report count", "reportCount": 1, "fallback": null }
      },
      "competitionRisk": "Low",
      "competitionRiskReason": "Estimated from very low public report count, recent target change, less obvious asset type.",
      "whyThisTarget": "Fresh wildcard scope expansion, with eligible and in scope, high bounty potential, low competition risk."
    }
  ],
  "meta": {
    "page": 1,
    "page_size": 250,
    "total": 9809,
    "total_pages": 40,
    "returned": 250,
    "has_more": true
  }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

Export up to 500 current platform or Self-Hosted targets in one bounded request. Each JSON row preserves its parent program_id.

Parameters and examples

Parameters

program_ids (array, optional; max: 50)

platforms (array, optional; max: 15)

tags (array, optional; max: 25)

opportunity_levels (array: elite|hot|strong|potential; platform programs only)

include_out_of_scope (bool; default: false)

include_ineligible (bool; default: false)

format (json|csv; default: json)

limit (default/max: 500)

Request body size (max: 65,536 bytes)

When program_ids is non-empty it is the authoritative selection; catalog filters are ignored

Paused program scopes require explicit program_ids and include_ineligible=true; their bounty eligibility remains false

cURL example

curl -sS -X POST "https://bbradar.io/api/v1/pro/targets/export" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"program_ids":["Self-Hosted:example-security"],"include_out_of_scope":false,"include_ineligible":false,"format":"json","limit":500}'

Example response

{
  "targets": [
    {
      "program_id": "Self-Hosted:example-security",
      "platform": "Self-Hosted",
      "program_handle": "example-security",
      "program_name": "Example Security",
      "catalog": "self_hosted",
      "target_type": "domain",
      "identifier": "api.example.com",
      "in_scope": true,
      "eligible_for_bounty": true,
      "wildcard": false,
      "is_active": true
    }
  ],
  "format": "json",
  "total": 1,
  "generated_at": "2026-08-25T09:00:00Z",
  "meta": {
    "returned": 1,
    "limit": 500,
    "has_more": false,
    "truncated": false,
    "programs_returned": 1
  }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

Retrieve latest target additions, updates, and removals with target, parent-program, and submission-cost intelligence.

Parameters and examples

Parameters

change_type (added|readded|updated|removed)

snapshot (optional; start on page 1, then reuse meta.snapshot with the same filters/account; expires after 5 minutes)

include_removed (bool, optional)

include_ineligible (bool, optional)

include_out_of_scope (bool, optional)

search (min length: 2, optional)

platforms (csv, optional)

tags (csv, optional; scope, language, or target-type tags)

minTargetScore (0-100, optional)

targetOpportunityLabel (Elite Target|Strong Target|Potential Target|Normal, optional)

competitionRisk (Low|Medium|High|Unknown, optional)

page (default: 1)

page_size (max: 100)

after_id (optional; incremental polling cursor, page must remain 1)

Cursor mode is oldest-first, scans at most 2,000 candidate rows, omits totals and facets, and returns next_after_id

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/targets/changes" \
  -G \
  --data-urlencode "change_type=added" \
  --data-urlencode "search=example" \
  --data-urlencode "minTargetScore=70" \
  --data-urlencode "targetOpportunityLabel=Strong Target" \
  --data-urlencode "competitionRisk=Low" \
  --data-urlencode "page=1" \
  --data-urlencode "page_size=50" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "results": [
    {
      "id": 48102,
      "change_type": "added",
      "changed_at": "2026-04-15T09:20:31Z",
      "program": {
        "id": "Sherlock:example-program",
        "handle": "example-program",
        "name": "Example Program",
        "platform": "Sherlock",
        "link": "https://audits.sherlock.xyz/bug-bounties/example-program",
        "scope_tags": ["domain", "api"],
        "bounty_min": 100,
        "bounty_max": 5000,
        "submission_cost": {
          "amount": 0,
          "maximum_amount": 250,
          "unit": "USDC",
          "kind": "deposit",
          "source": "sherlock_bug_bounties_api",
          "updated_at": "2026-04-16T07:45:02Z"
        },
        "profile_picture": "https://example.com/logo.png",
        "date_launched": "2026-03-04",
        "targets_updated_at": "2026-04-16T07:45:02Z",
        "competitionRisk": "Low",
        "competitionRiskReason": "Estimated from low public report count, less obvious asset type."
      },
      "target": {
        "identifier": "*.api.example.com",
        "normalized_identifier": "api.example.com",
        "display_name": "*.api.example.com",
        "type": "domain",
        "scope_tags": ["domain", "api"],
        "language_tags": ["javascript"],
        "in_scope": true,
        "eligible_for_bounty": true,
        "wildcard": true,
        "source_url": "https://example.com/policy",
        "added_at": "2026-04-15T09:20:31Z",
        "source_added_at": "2026-04-14",
        "last_seen": "2026-04-16T07:45:02Z",
        "is_active": true,
        "severity_score": 8.2,
        "severity_label": "High",
        "targetOpportunityScore": 87,
        "targetOpportunityLabel": "Elite Target",
        "targetScoreBreakdown": {
          "freshness": { "score": 35, "label": "Last 24 hours", "days": 0.4 },
          "targetType": { "score": 22, "label": "Wildcard", "key": "wildcard" },
          "reward": { "score": 18, "label": "Strong bounty", "maxBounty": 5000, "isNoReward": false },
          "reportActivity": { "score": 12, "label": "Low public report count", "reportCount": 4, "fallback": null }
        },
        "competitionRisk": "Low",
        "competitionRiskReason": "Estimated from low public report count, recent target change, less obvious asset type.",
        "whyThisTarget": "Fresh wildcard scope expansion, with eligible and in scope, strong reward potential, low competition risk."
      },
      "metadata": {},
      "diff": {}
    }
  ],
  "meta": {
    "page": 1,
    "page_size": 50,
    "total": 218,
    "total_pages": 5,
    "change_type": "added",
    "included_change_types": ["added"],
    "include_removed": false,
    "include_ineligible": false,
    "include_out_of_scope": false,
    "last_sync": "2026-04-16T07:45:02Z",
    "previous_sync": "2026-04-16T07:44:11Z",
    "applied_since": null
  },
  "facets": {
    "platforms": [
      { "value": "hackerone", "label": "HackerOne", "count": 120 }
    ],
    "tags": [
      { "value": "domain", "label": "domain", "count": 163 }
    ]
  }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

Retrieve bounded repository/ref transitions and their affected platform programs and targets. The response contains no patches, source code, commit messages, changed paths, filenames, or diff statistics.

Parameters and examples

Parameters

search (2-128 characters, optional; repository, ref, platform, program, or target)

platforms (csv, optional; max: 15)

tags (csv, optional; scope, language, or target-type tags; max: 25)

free_submission_only (bool; default: false)

snapshot (optional; start on page 1, then reuse meta.snapshot with the same filters/account; expires after 5 minutes)

include_removed (bool; default: false)

include_ineligible (bool; default: false)

include_out_of_scope (bool; default: false)

page (default: 1)

page_size (default: 50, max: 100)

after_id (optional; incremental polling cursor, page must remain 1)

include_targets (bool; default: true; false omits nested targets but preserves affected programs)

Cursor mode is oldest-first, skips the total-count query, and returns next_after_id

minTargetScore, targetOpportunityLabel, and competitionRisk require page mode and cannot be combined with after_id

Global facet aggregation is omitted so automation requests do not scan the full repository-link catalog

Requests exceeding 5,000 nested program/target associations return 413; narrow filters or page_size

Platform catalog only; Self-Hosted repository-change coverage is unavailable

cURL example

curl -sS -X GET "https://bbradar.io/api/v1/pro/repositories/changes" \
  -G \
  --data-urlencode "search=contracts" \
  --data-urlencode "platforms=Immunefi" \
  --data-urlencode "tags=solidity" \
  --data-urlencode "page=1" \
  --data-urlencode "page_size=50" \
  -H "Authorization: Bearer YOUR_PRO_API_KEY"

Example response

{
  "results": [
    {
      "id": 17042,
      "event_type": "push",
      "source": "poll",
      "ref_name": "main",
      "before_sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
      "after_sha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "observed_at": "2026-08-27T05:30:00Z",
      "repository": {
        "provider": "github",
        "provider_host": "github.com",
        "full_name": "example/contracts",
        "url": "https://github.com/example/contracts"
      },
      "changes_url": "https://github.com/example/contracts/compare/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "link_type": "compare",
      "programs": [
        { "id": "Immunefi:example", "platform": "Immunefi", "handle": "example", "name": "Example Protocol" }
      ],
      "targets": [
        {
          "id": 901,
          "type": "source code",
          "identifier": "https://github.com/example/contracts",
          "path_kind": "repository",
          "path_prefix": null,
          "in_scope": true,
          "eligible_for_bounty": true,
          "is_active": true,
          "scope_tags": ["smart contract", "source code"],
          "language_tags": ["solidity"]
        }
      ]
    }
  ],
  "meta": { "page": 1, "page_size": 50, "total": 1, "total_pages": 1 }
}

See Errors and retries for invalid requests, authentication, expiry, size limits, and temporary failures.

Rate and concurrency limits

Programs and opportunities80 requests/min

/programs and /opportunities/{level} share this endpoint bucket.

Targets, search, and export40 requests/min

/programs/{program_id}/targets, /targets/search, and /targets/export share this endpoint bucket.

Target and repository changes30 requests/min

/targets/changes and /repositories/changes share this endpoint bucket.

Global key bucket120 requests/min, burst 300

Shared by all Pro API v1 requests for the same API key.

Per key + IP bucket60 requests/min

Applied to one API key from one source IP.

Concurrent requests8 per key, 3 change feeds

Target and repository changes share a smaller concurrent cap because they are the heaviest endpoints.

Distinct IP guard5 IPs/hour

Exceeding this locks the key for 10 minutes. Three locks in 24 hours locks it for 24 hours.

Responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. A 429 response also includes Retry-After.

Errors and retries

Retry only transient failures, reduce concurrency, and use jitter to avoid synchronized traffic.

400

Invalid parameter or request shape.

Correct the request; do not retry it unchanged.

401

Missing, malformed, revoked, or incorrect API key.

Check the Bearer header and the current key.

402

The account no longer has active Pro access.

Restore Pro access before retrying.

404

The requested program or resource was not found.

Verify the composite program ID and URL encoding.

410

A snapshot expired or the change cursor predates retained history.

Start a fresh snapshot on page 1, or reconcile current inventory before restarting the change cursor.

413

A request body, snapshot, or repository association result exceeds its size limit.

Narrow the selection or reduce the page size; do not retry the same oversized request.

423

The key is temporarily locked by abuse protection.

Stop traffic and wait until the lock expires.

429

A rate or concurrency limit was exceeded.

Honor Retry-After and retry with exponential jitter.

503

A required service is temporarily unavailable.

Honor Retry-After when present and retry with bounded backoff.