Skip to content

API reference ​

Use the Exploit Shield API to read and manage your exposures, reports, vendors, configurations, alerting, and users from your own scripts and tools, such as a SIEM.

Get started ​

Send HTTPS requests to the API host for your organization:

text
https://api.<your-domain>

<your-domain> is the domain of your Exploit Shield dashboard.

  • All endpoints, except the health check, start with /v1. For example, https://api.<your-domain>/v1/secrets.
  • Send request bodies as JSON with the Content-Type: application/json header. All responses are JSON.
  • Use HTTPS. HTTP requests are redirected to HTTPS.

To check that your API key works, get your own user record:

bash
curl -H "Authorization: Bearer $EXPLOIT_SHIELD_API_KEY" \
  "https://api.<your-domain>/v1/users/me"

Authentication ​

Every /v1 request needs an API key in the Authorization header:

http
Authorization: Bearer <your-api-key>

To create a key, see API keys. A request with a key succeeds only when:

  • The key isn't expired or archived.
  • The key owner's sign-in account is confirmed, enabled, and not locked.
  • The key owner is listed on the Users page.

When you archive a key or someone disables a sign-in account, the change takes effect within about one minute. Role changes and removals from the Users page take effect on the next request.

Permissions ​

A request runs with the current role of the key owner. For more information about roles, see Roles.

RoleWhat the role can do
user, viewer, manager, analystCall all GET endpoints, except Search users and List users by role.
adminCall all endpoints, including every POST, PUT, PATCH, and DELETE request.

Protect secret values ​

Responses contain live secrets

Exposure responses include the full secret value in the secret_value field, and every role can read them. Treat API responses as you treat the credentials themselves:

  • Store your API key in a secret manager.
  • Don't write raw responses to logs.
  • Before you forward exposures to another tool, such as a SIEM, remove secret_value unless the tool needs it.

Pagination ​

Endpoints that return pages accept these query parameters:

ParameterTypeDefaultDescription
limitinteger50Maximum number of items in the response, from 1 to 100.
offsetinteger0Position of the first item to return, starting at 0.

A page looks like this:

json
{
  "items": [],
  "total": 142,
  "limit": 50,
  "offset": 0
}

To get the next page, add limit to offset. Stop when offset plus the number of items is equal to or greater than total.

Results are sorted by id in ascending order, with these exceptions:

  • Vendors are sorted by vendor_name.
  • Vendor incidents are sorted newest first.
  • Alert events are sorted newest first.

Pages are stable while the data doesn't change. Items that are added or changed between requests can move to a different page. To collect new items over time, store the highest id that you received.

Rate limits ​

Each client IP address can send up to 20 requests per second, with bursts of up to 40 requests. If you send more, the API returns 429 Too Many Requests with a Retry-After header. Wait the number of seconds in Retry-After, and then try again.

Errors ​

Errors return a JSON object with a detail message. Most errors also include an error_code. Validation errors (422) also include an errors list:

json
{
  "detail": "Validation failed",
  "error_code": "VALIDATION_ERROR",
  "errors": [
    {
      "type": "validation_error",
      "loc": ["body", "user_email"],
      "msg": "field required",
      "input": ""
    }
  ]
}
Statuserror_codeMeaning
400 Bad RequestThe action isn't allowed. For example, you tried to delete your own user.
401 UnauthorizedThe API key is missing, unknown, expired, or archived. Or the key owner isn't on the Users page, or their sign-in account is unconfirmed, disabled, or locked. Retrying doesn't help.
403 ForbiddenYour role can't call this endpoint, or you can't make this change, such as changing your own role. Write requests need the admin role.
404 Not FoundNOT_FOUNDThe record doesn't exist or was deleted.
409 ConflictCONFLICTThe record already exists, such as a duplicate configuration or user email. Also returned when you try to change the name or domain of a vendor.
422 Unprocessable EntityVALIDATION_ERRORA query parameter or body field isn't valid.
429 Too Many RequestsYou exceeded the rate limit. Wait for the time in Retry-After.
500 Internal Server ErrorINTERNAL_ERROR or DATABASE_ERRORAn unexpected error occurred. Try again later. If the error continues, send email to support@exploitstrike.com.
503 Service UnavailableThe sign-in service is temporarily unavailable. Try again with backoff.

Data formats ​

  • Timestamps use ISO 8601. Most timestamps end in Z (UTC). repo_commit_date has no time zone offset.
  • Severity uses two scales:
    • Exposures, configurations, and vendor incidents use 0 to 10. A severity of 8 or higher is high.
    • Alert rules and alert events use 1 to 4: 1 is Low, 2 is Medium, 3 is High, and 4 is Critical.
  • JSON in strings. Some fields contain a JSON document encoded as a string: result_data, details, scorecard_data, and delivery_results_json. Parse the string to read the values.
  • Deleted records aren't returned. The deleted field in responses is always false.

Versions and compatibility ​

The API version is part of the path, such as /v1. Use only the endpoints, parameters, and fields in this reference. Anything that isn't documented here can change or be removed without notice.

Changes we can make at any time ​

We can make these changes to /v1 without notice. Build your integration so that it keeps working when they happen:

  • Add endpoints.
  • Add optional query parameters and optional request body fields.
  • Add fields to responses. Ignore fields that you don't recognize.
  • Add values to fields that have a fixed set of values, such as type, status, category, or secret_type. Handle values that you don't recognize.
  • Change the order of fields in a response.
  • Change the text of error messages. To handle errors, use the HTTP status code and error_code, not the detail text.
  • Fix behavior that doesn't match this reference.

Breaking changes ​

A breaking change is a change that can stop a correct integration from working. For example:

  • Removing or renaming an endpoint, parameter, or field.
  • Changing the type or format of a field.
  • Making an optional parameter or field required.
  • Changing the meaning of an existing value.

We don't make breaking changes to /v1 without notice. Before a breaking change takes effect, we announce it in the Changelog. For large changes, we can release a new version, such as /v2.

To protect your data, we can make a breaking change without notice when it's needed to fix a security issue. We announce these changes in the Changelog.

Request logging ​

Exploit Shield logs every /v1 request with the user, method, path, query string, status code, duration, client IP address, user agent, and request ID.

Endpoints ​

AreaMethodPathRoleDescription
ExposuresGET/v1/secretsAnyList exposures
ExposuresGET/v1/secrets/searchAnySearch exposures
ExposuresGET/v1/secrets/summaryAnyCount exposures by group
ExposuresGET/v1/secrets/by-severity/{severity}AnyList exposures by severity
ExposuresGET/v1/secrets/unalertedAnyList unalerted exposures
ExposuresGET/v1/secrets/unremediatedAnyList unremediated exposures
ExposuresGET/v1/secrets/{secret_id}AnyGet an exposure
ExposuresPATCH/v1/secrets/{secret_id}/false-positiveadminMark an exposure as a false positive
ExposuresPATCH/v1/secrets/{secret_id}/remediatedadminMark an exposure as remediated
ExposuresPATCH/v1/secrets/bulk/false-positiveadminMark exposures as false positives in bulk
ExposuresPATCH/v1/secrets/bulk/remediatedadminMark exposures as remediated in bulk
ReportsGET/v1/attribution-resultsAnyList reports
ReportsGET/v1/attribution-results/summaryAnyCount reports by group
ReportsGET/v1/attribution-results/{result_id}AnyGet a report
ReportsPATCH/v1/attribution-results/{result_id}/false-positiveadminMark a report as a false positive
ReportsPATCH/v1/attribution-results/{result_id}/remediatedadminMark a report as remediated
ReportsPATCH/v1/attribution-results/bulk/false-positiveadminMark reports as false positives in bulk
ReportsPATCH/v1/attribution-results/bulk/remediatedadminMark reports as remediated in bulk
VendorsGET/v1/vendorsAnyList vendors
VendorsGET/v1/vendors/{vendor_id}/incidentsAnyList vendor incidents
VendorsGET/v1/vendors/{vendor_id}/scorecardAnyGet a vendor scorecard
VendorsPATCH/v1/vendor-incidents/{incident_id}/false-positiveadminMark a vendor incident as a false positive
VendorsPATCH/v1/vendor-incidents/{incident_id}/acknowledgedadminAcknowledge a vendor incident
ConfigurationsGET/v1/configAnyList configurations
ConfigurationsGET/v1/config/searchAnySearch configurations
ConfigurationsGET/v1/config/third-partyAnyList third-party configurations
ConfigurationsGET/v1/config/blacklistedAnyList blocklisted configurations
ConfigurationsGET/v1/config/{config_id}AnyGet a configuration
ConfigurationsPOST/v1/configadminCreate a configuration
ConfigurationsPUT/v1/config/{config_id}adminUpdate a configuration
ConfigurationsDELETE/v1/config/{config_id}adminDelete a configuration
AlertingGET/v1/alerting/destinationsAnyList alert destinations
AlertingPOST/v1/alerting/destinationsadminCreate an alert destination
AlertingPATCH/v1/alerting/destinations/{destination_id}adminUpdate an alert destination
AlertingDELETE/v1/alerting/destinations/{destination_id}adminDelete an alert destination
AlertingGET/v1/alerting/rulesAnyList alert rules
AlertingPOST/v1/alerting/rulesadminCreate an alert rule
AlertingPATCH/v1/alerting/rules/{rule_id}adminUpdate an alert rule
AlertingDELETE/v1/alerting/rules/{rule_id}adminDelete an alert rule
AlertingGET/v1/alerting/eventsAnyList alert events
UsersGET/v1/users/meAnyGet the current user
UsersGET/v1/usersAnyList users
UsersGET/v1/users/searchadminSearch users
UsersGET/v1/users/by-role/{role}adminList users by role
UsersGET/v1/users/{user_id}AnyGet a user
UsersPOST/v1/usersadminCreate a user
UsersPUT/v1/users/{user_id}adminUpdate a user
UsersDELETE/v1/users/{user_id}adminDelete a user
StatisticsGET/v1/stats/secretsAnyGet exposure counts
StatisticsGET/v1/stats/usersAnyGet user counts
StatisticsGET/v1/stats/configsAnyGet configuration counts
StatisticsGET/v1/stats/scorecardAnyGet the organization scorecard
ChangelogGET/v1/changelogAnyGet the changelog
HealthGET/healthNoneCheck API health

Exposures ​

An exposure is a leaked credential, token, key, or other sensitive value that Exploit Shield found for your organization. For more information, see Exposures.

Exposure object ​

json
{
  "id": 101,
  "label": "secrets",
  "secret_type": "AWS_ACCESS_KEY_ID",
  "secret_key": "AWS_ACCESS_KEY_ID",
  "secret_value": "AKIAIOSFODNN7EXAMPLE",
  "comment": "Found in deployment script",
  "file_reference": "deploy/env.sh",
  "line_reference": 25,
  "preview_lines": "24: export AWS_REGION=us-east-1\n25: export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE",
  "repo_link": "https://github.com/example-org/infra",
  "repo_commit": "4f8a2b1c9d0e",
  "repo_commit_date": "2026-08-15T14:22:00",
  "repo_branch": "main",
  "severity": 9,
  "assigned_to": null,
  "remediation_status": "pending",
  "affected_system": "production",
  "alerted": true,
  "repo_remediated": false,
  "false_positive": false,
  "deleted": false
}
FieldTypeDescription
idintegerExposure ID.
labelstring or nullCategory label.
secret_typestring or nullType of secret, such as API_KEY or AWS_ACCESS_KEY_ID.
secret_keystring or nullVariable name or key name in the source file.
secret_valuestring or nullThe full secret value. See Protect secret values.
commentstring or nullNote about the exposure.
file_referencestring or nullPath of the file in the repository or source.
line_referenceinteger or nullLine number of the exposure, starting at 1.
preview_linesstring or nullLines around the exposure.
repo_linkstring or nullURL of the repository or source.
repo_commitstring or nullCommit SHA.
repo_commit_datestring or nullCommit date, without a time zone offset.
repo_branchstring or nullBranch name.
severityinteger or nullSeverity from 0 to 10. 8 or higher is high.
assigned_tointeger or nullID of the user that the exposure is assigned to.
remediation_statusstring or nullRemediation state as text, such as pending.
affected_systemstring or nullAffected system or environment.
alertedbooleantrue if an alert was sent for the exposure.
repo_remediatedbooleantrue if the exposure is marked as remediated.
false_positivebooleantrue if the exposure is marked as a false positive.
deletedbooleanAlways false.

List exposures ​

GET /v1/secrets

Returns a page of exposure objects.

Search exposures ​

GET /v1/secrets/search

Returns a page of exposure objects that match all the filters you send. Text filters match any part of the value.

  • Role: Any
ParameterTypeDescription
secret_typestringText in secret_type.
severityintegerExact severity, from 0 to 10.
remediation_statusstringText in remediation_status.
repo_linkstringText in repo_link.
file_referencestringText in file_reference.
secret_keystringText in secret_key.
commentstringText in comment.
repo_branchstringText in repo_branch.
affected_systemstringText in affected_system.
alertedbooleantrue or false.
repo_remediatedbooleantrue or false.
false_positivestringshow returns all exposures, hide excludes false positives, and only returns only false positives.
limit, offsetintegerSee Pagination.
bash
curl -H "Authorization: Bearer $EXPLOIT_SHIELD_API_KEY" \
  "https://api.<your-domain>/v1/secrets/search?false_positive=hide&repo_remediated=false&limit=50&offset=0"

Count exposures by group ​

GET /v1/secrets/summary

Returns the number of exposures for each value of a field, with the largest count first.

  • Role: Any
  • Query parameters: group_by is one of secret_type (default), severity, remediation_status, repo_link, or file_reference.
json
[
  {
    "group_key": "AWS_ACCESS_KEY_ID",
    "transaction_count": 42
  }
]

transaction_count is the number of exposures in the group.

List exposures by severity ​

GET /v1/secrets/by-severity/{severity}

Returns a list, not a page, of exposure objects with the exact severity.

  • Role: Any
  • Path parameters: severity is an integer from 0 to 10.

List unalerted exposures ​

GET /v1/secrets/unalerted

Returns a page of exposure objects where alerted is false.

List unremediated exposures ​

GET /v1/secrets/unremediated

Returns a page of exposure objects where repo_remediated is false.

Get an exposure ​

GET /v1/secrets/{secret_id}

Returns one exposure object.

  • Role: Any
  • Path parameters: secret_id is the exposure ID.

Mark an exposure as a false positive ​

PATCH /v1/secrets/{secret_id}/false-positive

Sets or clears the false positive flag on one exposure. Returns the updated exposure object.

  • Role: admin
  • Path parameters: secret_id is the exposure ID.
json
{
  "false_positive": true
}

Mark an exposure as remediated ​

PATCH /v1/secrets/{secret_id}/remediated

Sets or clears the remediated flag on one exposure. Returns the updated exposure object.

  • Role: admin
  • Path parameters: secret_id is the exposure ID.
json
{
  "secret_id": 101,
  "repo_remediated": true
}

The body must include secret_id. The API updates the exposure in the path.

Mark exposures as false positives in bulk ​

PATCH /v1/secrets/bulk/false-positive

Sets or clears the false positive flag on several exposures.

  • Role: admin
json
{
  "secret_ids": [101, 102, 105],
  "false_positive": true
}

Response:

json
{
  "total_count": 3,
  "updated_count": 2,
  "failed_ids": [105]
}

total_count is the number of distinct IDs that you sent. failed_ids lists the IDs that weren't found.

Mark exposures as remediated in bulk ​

PATCH /v1/secrets/bulk/remediated

Sets or clears the remediated flag on several exposures. The response has the same fields as Mark exposures as false positives in bulk.

  • Role: admin
json
{
  "secret_ids": [101, 102, 105],
  "repo_remediated": true
}

Reports ​

A report is an attribution analysis of a repository. It includes ownership, severity, confidence, and evidence. For more information, see Reports.

Report object ​

json
{
  "id": 12,
  "repo_link": "https://github.com/example-org/service-api",
  "repo_commit": "abc123def456",
  "repo_commit_date": "2026-08-20T09:15:00",
  "repo_branch": "main",
  "result_data": "{\"severity\": \"High\", \"confidence\": 85, \"ownership\": \"first-party\"}",
  "engine": "attribution-v1",
  "ownership": "first-party",
  "remediated": false,
  "false_positive": false
}
FieldTypeDescription
idintegerReport ID.
repo_linkstring or nullURL of the repository or source.
repo_commitstring or nullCommit SHA.
repo_commit_datestring or nullCommit date, without a time zone offset.
repo_branchstring or nullBranch name.
result_datastring or nullThe report as a JSON string, with severity, confidence, summary, evidence, and the report text in Markdown.
enginestring or nullName of the analysis that created the report.
ownershipstring or nullfirst-party, third-party, or joint. The dashboard and scorecard count a report with no value as first-party.
remediatedbooleantrue if the report is marked as remediated.
false_positivebooleantrue if the report is marked as a false positive.

List reports ​

GET /v1/attribution-results

Returns a page of report objects that match all the filters you send.

  • Role: Any
ParameterTypeDescription
repo_commitstringExact commit SHA.
repo_branchstringExact branch name.
repo_linkstringExact repository URL.
enginestringText in engine.
remediatedbooleantrue or false.
false_positivebooleantrue or false.
ownershipstringOne exact value: first-party, third-party, or joint. Reports with no ownership value don't match.
ownership_instringComma-separated values, such as first-party,joint. If the list includes first-party, reports with no ownership value also match.
limit, offsetintegerSee Pagination.

To get the same open first-party reports that the dashboard shows, use ownership_in:

bash
curl -H "Authorization: Bearer $EXPLOIT_SHIELD_API_KEY" \
  "https://api.<your-domain>/v1/attribution-results?false_positive=false&remediated=false&ownership_in=first-party&limit=50&offset=0"

Count reports by group ​

GET /v1/attribution-results/summary

Returns the number of reports for each value of a field, with the largest count first. The response has the same format as Count exposures by group.

  • Role: Any
  • Query parameters: group_by is one of repo_branch (default), repo_link, remediated, or false_positive.

Get a report ​

GET /v1/attribution-results/{result_id}

Returns one report object.

  • Role: Any
  • Path parameters: result_id is the report ID.

Mark a report as a false positive ​

PATCH /v1/attribution-results/{result_id}/false-positive

Sets or clears the false positive flag on one report. Returns the updated report object.

  • Role: admin
  • Path parameters: result_id is the report ID.
json
{
  "false_positive": true
}

Mark a report as remediated ​

PATCH /v1/attribution-results/{result_id}/remediated

Sets or clears the remediated flag on one report. Returns the updated report object.

  • Role: admin
  • Path parameters: result_id is the report ID.
json
{
  "remediated": true
}

Mark reports as false positives in bulk ​

PATCH /v1/attribution-results/bulk/false-positive

Sets or clears the false positive flag on several reports. The response has the same fields as Mark exposures as false positives in bulk.

  • Role: admin
json
{
  "result_ids": [12, 15],
  "false_positive": true
}

Mark reports as remediated in bulk ​

PATCH /v1/attribution-results/bulk/remediated

Sets or clears the remediated flag on several reports. The response has the same fields as Mark exposures as false positives in bulk.

  • Role: admin
json
{
  "result_ids": [12, 15],
  "remediated": true
}

Vendors ​

Vendors are the third parties that you monitor. Each vendor has incidents and a score. For more information, see Vendors.

List vendors ​

GET /v1/vendors

Returns a list of your monitored vendors, sorted by name, with the number of incidents and the date of the latest incident.

  • Role: Any
json
[
  {
    "id": 4,
    "vendor_name": "Acme Cloud",
    "cnames": ["acmecloud.example"],
    "incident_count": 3,
    "latest_incident_date": "2026-09-10T12:00:00Z",
    "created_at": "2026-07-01T00:00:00Z",
    "updated_at": "2026-09-10T12:00:00Z"
  }
]

List vendor incidents ​

GET /v1/vendors/{vendor_id}/incidents

Returns a page of incidents for one vendor, newest first.

  • Role: Any
  • Path parameters: vendor_id is the vendor ID.
  • Query parameters:
    • severity (optional): Exact severity, from 0 to 10.
    • false_positive (optional): true or false.
    • limit and offset
json
{
  "items": [
    {
      "id": 27,
      "vendor_id": 4,
      "incident_key": "acmecloud:secret_exposure:9f8e7d",
      "short_summary": "2 secrets exposed in public repository",
      "severity": 8,
      "category": "secret_exposure",
      "incident_date": "2026-09-10T12:00:00Z",
      "confidence": 92,
      "scorecard_data": "{\"secret_count\": 2, \"platform\": \"github\"}",
      "false_positive": false,
      "acknowledged": false,
      "created_at": "2026-09-10T12:05:00Z",
      "updated_at": "2026-09-10T12:05:00Z"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

Get a vendor scorecard ​

GET /v1/vendors/{vendor_id}/scorecard

Returns the vendor's score from 0 to 100 and its breakdowns. Incidents that are marked as false positives don't count. For more information, see Scoring and attribution.

  • Role: Any
  • Path parameters: vendor_id is the vendor ID.
json
{
  "vendor_id": 4,
  "vendor_name": "Acme Cloud",
  "score": 88,
  "total_incidents": 3,
  "active_incidents": 2,
  "false_positive_incidents": 1,
  "severity_counts": { "high": 1, "medium": 1 },
  "category_counts": { "secret_exposure": 2 },
  "aggregate_metrics": { "secret_count": 3.0 },
  "latest_incident_date": "2026-09-10T12:00:00Z",
  "severity_timeline": [
    { "date": "2026-09", "critical": 0, "high": 1, "medium": 1 }
  ],
  "indicator_breakdown": [
    { "name": "secret_exposure", "count": 2, "pct": 100 }
  ],
  "platform_breakdown": [
    { "name": "github", "count": 2, "pct": 100 }
  ]
}

Mark a vendor incident as a false positive ​

PATCH /v1/vendor-incidents/{incident_id}/false-positive

Sets or clears the false positive flag on one incident. Incidents that are marked as false positives don't count toward the vendor's score. Returns the updated incident.

  • Role: admin
  • Path parameters: incident_id is the incident ID.
json
{
  "false_positive": true
}

Acknowledge a vendor incident ​

PATCH /v1/vendor-incidents/{incident_id}/acknowledged

Sets or clears the acknowledged flag on one incident. Returns the updated incident.

  • Role: admin
  • Path parameters: incident_id is the incident ID.
json
{
  "acknowledged": true
}

Configurations ​

Configurations are the domains, keywords, integrations, and vendors that Exploit Shield monitors for you. A new configuration is Pending until Exploit Strike reviews it, and then it's Active. For more information, see Configurations.

Add and change configurations in the dashboard

A domain and its keywords are stored as separate records, and the dashboard keeps them in sync. We recommend that you add and change configurations on the Configurations page, and use the API to read them.

Configuration object ​

json
{
  "id": 7,
  "risk_keyword": "example.com",
  "risk_location": "domain",
  "risk_severity": 1,
  "is_third_party": false,
  "is_blacklisted": false,
  "alert_type": "none",
  "alert_recipient": null,
  "details": "{\"kind\": \"domain\", \"keywords\": [\"example\"], \"notes\": \"Primary corporate domain\"}",
  "deleted": false,
  "approved": false
}
FieldTypeDescription
idintegerConfiguration ID. The API assigns it.
risk_keywordstring or nullThe monitored value: a domain, keyword, integration match value, or vendor name. See Configuration types.
risk_locationstring or nullType of configuration: domain, integration, or vendor. Keywords use domain.
risk_severityinteger or nullSeverity from 0 to 10. The dashboard sets 1, or 8 for a critical vendor.
is_third_partybooleantrue for vendors.
is_blacklistedbooleanBlocklist flag. The dashboard sets false.
alert_typestringnone, email, or sms. This field doesn't send alerts. To send alerts, use alert rules.
alert_recipientinteger or nullA user ID. This field doesn't send alerts.
detailsstring or nullMore settings as a JSON string. The format depends on the type. See Configuration types.
deletedbooleanAlways false. To delete a configuration, see Delete a configuration.
approvedbooleanfalse while Pending and true when Active. Only Exploit Strike can change it.

Configuration types ​

Typerisk_locationrisk_keyworddetails
DomaindomainThe domain, such as example.com{"kind": "domain", "keywords": ["example"], "notes": "..."}
KeyworddomainThe keyword, such as example{"kind": "keyword", "parent_domain": "example.com"}
IntegrationintegrationThe value to match{"serviceName": "Okta", "matchType": "subdomain", "notes": "..."}. matchType is subdomain, path, or string.
VendorvendorThe vendor name{"kind": "vendor", "domains": ["vendor.example"], "isCritical": true}

notes is optional. A domain lists its keywords in keywords, and each keyword is also a separate configuration that names the domain in parent_domain.

List configurations ​

GET /v1/config

Returns a page of configuration objects.

Search configurations ​

GET /v1/config/search

Returns a page of configuration objects that match all the filters you send.

  • Role: Any
ParameterTypeDescription
risk_keywordstringText in risk_keyword.
risk_locationstringText in risk_location, such as vendor.
risk_severityintegerExact severity, from 0 to 10.
is_third_partybooleantrue or false.
is_blacklistedbooleantrue or false.
limit, offsetintegerSee Pagination.

List third-party configurations ​

GET /v1/config/third-party

Returns a page of configuration objects where is_third_party is true.

List blocklisted configurations ​

GET /v1/config/blacklisted

Returns a page of configuration objects where is_blacklisted is true.

Get a configuration ​

GET /v1/config/{config_id}

Returns one configuration object.

  • Role: Any
  • Path parameters: config_id is the configuration ID.

Create a configuration ​

POST /v1/config

Creates a configuration and returns the new configuration object. The new configuration is Pending until Exploit Strike reviews it.

Returns 409 Conflict if an active configuration already covers the same domain, the same keyword for the domain, the same integration match, or the same vendor.

Update a configuration ​

PUT /v1/config/{config_id}

Changes the fields that you send and returns the updated configuration object. The API ignores id, approved, and deleted.

  • Role: admin
  • Path parameters: config_id is the configuration ID.

You can't change the name or domain of a vendor. The API returns 409 Conflict. To change them, delete the vendor and create it again.

Delete a configuration ​

DELETE /v1/config/{config_id}

Deletes one configuration.

  • Role: admin
  • Path parameters: config_id is the configuration ID.
json
{
  "message": "Configuration deleted successfully"
}
  • Deleting a domain doesn't delete its keywords. Delete each keyword too.
  • When you delete the last configuration for a vendor, the vendor no longer appears in List vendors.

Alerting ​

Alerting sends new reports to your webhooks. An alert rule decides which reports to send, and an alert destination is a webhook that receives them. For more information, see Alerting.

List alert destinations ​

GET /v1/alerting/destinations

Returns a list of alert destinations.

  • Role: Any
json
[
  {
    "id": 1,
    "type": "siem",
    "label": "SOC Webhook",
    "endpoint": "https://siem.example.com/webhooks/exploitshield",
    "enabled": true,
    "created_at": "2026-08-25T15:00:00Z",
    "updated_at": "2026-08-25T15:00:00Z"
  }
]

Create an alert destination ​

POST /v1/alerting/destinations

Creates an alert destination and returns it.

  • Role: admin
FieldTypeRequiredDescription
typestringYesdiscord, teams, google_chat, siem, cti, or other.
labelstring or nullNoDisplay name.
endpointstringYesWebhook URL that receives alerts.
enabledbooleanNoDefault is true.

Update an alert destination ​

PATCH /v1/alerting/destinations/{destination_id}

Changes the fields that you send (type, label, endpoint, or enabled) and returns the updated destination.

  • Role: admin
  • Path parameters: destination_id is the destination ID.

Delete an alert destination ​

DELETE /v1/alerting/destinations/{destination_id}

Deletes an alert destination and removes it from your alert rules.

  • Role: admin
  • Path parameters: destination_id is the destination ID.
json
{
  "message": "Alert destination deleted successfully"
}

List alert rules ​

GET /v1/alerting/rules

Returns a list of alert rules.

  • Role: Any
json
[
  {
    "id": 1,
    "name": "high-confidence-reports",
    "source": "attribution_report",
    "enabled": true,
    "destination_ids": [1],
    "min_severity_numeric": 3,
    "min_confidence_numeric": 80,
    "created_at": "2026-08-25T15:05:00Z",
    "updated_at": "2026-08-25T15:05:00Z"
  }
]

Create an alert rule ​

POST /v1/alerting/rules

Creates an alert rule and returns it.

  • Role: admin
FieldTypeRequiredDescription
namestringYesRule name. Must be unique, up to 255 characters.
sourcestringNoattribution_report, which is the default and the only value.
enabledbooleanNoDefault is true.
destination_idslist of integersYesIDs of one or more existing destinations.
min_severity_numericinteger or nullNoLowest severity to send, from 1 (Low) to 4 (Critical).
min_confidence_numericinteger or nullNoLowest confidence to send, from 0 to 100.

Update an alert rule ​

PATCH /v1/alerting/rules/{rule_id}

Changes the fields that you send and returns the updated rule. You can send any field from Create an alert rule.

  • Role: admin
  • Path parameters: rule_id is the rule ID.

Delete an alert rule ​

DELETE /v1/alerting/rules/{rule_id}

Deletes an alert rule.

  • Role: admin
  • Path parameters: rule_id is the rule ID.
json
{
  "message": "Alert rule deleted successfully"
}

List alert events ​

GET /v1/alerting/events

Returns a page of alert events, newest first. An alert event records one alert and its delivery to each destination.

json
{
  "items": [
    {
      "id": 9,
      "rule_id": 1,
      "rule_name": "high-confidence-reports",
      "subject_type": "attribution_report",
      "subject_id": "12",
      "severity_numeric": 3,
      "severity_label": "High",
      "title": "High confidence attribution report",
      "delivery_results_json": "[{\"destination_id\": 1, \"status_code\": 200, \"ok\": true}]",
      "status": "sent",
      "created_at": "2026-08-25T16:00:00Z",
      "updated_at": "2026-08-25T16:00:00Z"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

status is sent, partial, or failed. subject_id is the report ID.

Users ​

Users are the people and integrations that can sign in to Exploit Shield or use an API key. For more information, see Users and Roles.

User object ​

json
{
  "id": 1,
  "user_role": "admin",
  "user_name": "Jane Doe",
  "user_email": "jane.doe@example.com",
  "user_phone": "+14155552671"
}

Get the current user ​

GET /v1/users/me

Returns the user object of the API key owner. Use it to test a new API key.

  • Role: Any

List users ​

GET /v1/users

Returns a page of user objects.

Search users ​

GET /v1/users/search

Returns a page of user objects that match all the filters you send.

  • Role: admin
  • Query parameters:
    • user_role (optional): Exact role.
    • user_email (optional): Text in the email address.
    • limit and offset

List users by role ​

GET /v1/users/by-role/{role}

Returns a list, not a page, of user objects with the role.

  • Role: admin
  • Path parameters: role is admin, user, viewer, manager, or analyst.

Get a user ​

GET /v1/users/{user_id}

Returns one user object.

  • Role: Any
  • Path parameters: user_id is the user ID.

Create a user ​

POST /v1/users

Creates a user and returns the new user object.

  • Role: admin
json
{
  "user_role": "analyst",
  "user_name": "SOC SIEM poller",
  "user_email": "siem@example.com",
  "user_phone": "+14155550199"
}
FieldTypeRequiredDescription
user_rolestringYesadmin, user, viewer, manager, or analyst.
user_namestringYesDisplay name.
user_emailstringYesEmail address. It must be unique, and it's stored in lowercase.
user_phonestring or nullNoPhone number in E.164 format, such as +14155550199. US numbers without a country code are also accepted. The API stores numbers in E.164 format and returns 422 for a number that isn't valid. An empty string clears the number.

Returns 409 Conflict if a user with the email address already exists.

Update a user ​

PUT /v1/users/{user_id}

Updates a user and returns the updated user object.

  • Role: admin
  • Path parameters: user_id is the user ID.
  • Body: user_role and user_name are required. user_email and user_phone are optional. The fields have the same format as in Create a user. If you send a phone number that's different from the stored number, it must be valid.

You can't change your own role. The API returns 403 Forbidden. Ask another admin to change it.

Delete a user ​

DELETE /v1/users/{user_id}

Deletes a user. API keys that the user owns stop working right away.

  • Role: admin
  • Path parameters: user_id is the user ID.
json
{
  "message": "User deleted successfully"
}

You can't delete your own user. The API returns 400 Bad Request.

Statistics ​

Statistics return the counts and scores that the dashboard shows. For more information, see Dashboard home.

Get exposure counts ​

GET /v1/stats/secrets

Returns exposure counts.

  • Role: Any
json
{
  "total_secrets": 120,
  "alerted_secrets": 95,
  "remediated_secrets": 40,
  "high_severity_secrets": 18,
  "unalerted_secrets": 25,
  "unremediated_secrets": 80
}

high_severity_secrets counts exposures with a severity of 8 or higher.

Get user counts ​

GET /v1/stats/users

Returns user counts.

  • Role: Any
json
{
  "total_users": 8,
  "admin_users": 2,
  "regular_users": 4
}

regular_users counts only users with the user role. Users with the viewer, manager, or analyst role count only in total_users.

Get configuration counts ​

GET /v1/stats/configs

Returns configuration counts.

  • Role: Any
json
{
  "total_configs": 15,
  "third_party_configs": 10,
  "blacklisted_configs": 0,
  "high_risk_configs": 6
}

high_risk_configs counts configurations with a severity of 8 or higher.

Get the organization scorecard ​

GET /v1/stats/scorecard

Returns your organization's score and breakdowns. The score uses exposures that aren't false positives and open reports.

  • Role: Any
json
{
  "total_exposures": 115,
  "unremediated_exposures": 75,
  "high_severity_exposures": 16,
  "total_reports": 14,
  "open_reports": 4,
  "first_party_open_reports": 2,
  "third_party_open_reports": 2,
  "score": 84,
  "critical_open_reports": 0,
  "false_positive_reports": 1,
  "remediated_reports": 10,
  "avg_dwell_days": 12.5,
  "latest_report_date": "2026-09-18T10:30:00Z",
  "severity_counts": { "high": 2, "medium": 2 },
  "ownership_counts": { "first-party": 2, "third-party": 2 },
  "source_counts": { "github": 3, "postman": 1 },
  "severity_timeline": [
    { "date": "2026-09", "critical": 0, "high": 2, "medium": 2 }
  ],
  "indicator_breakdown": [
    { "name": "domain", "count": 3, "pct": 75 },
    { "name": "keyword", "count": 1, "pct": 25 }
  ],
  "platform_breakdown": [
    { "name": "github", "count": 3, "pct": 75 },
    { "name": "postman", "count": 1, "pct": 25 }
  ]
}

Changelog ​

Get the changelog ​

GET /v1/changelog

Returns the product changelog in Markdown. For more information, see Changelog.

  • Role: Any
json
{
  "markdown": "# Changelog\n...",
  "last_updated": "2026-10-01T00:00:00Z"
}

Health ​

Check API health ​

GET /health

Returns 200 OK with "status": "healthy" when the API is available. Use it for uptime monitoring. This endpoint doesn't need an API key.