Search endpoints (POST …/search) and bulk actions (POST …/search:<action>) take the same JSON body, except for a few searches with a format of their own (see Searches With Another Filter Format below):

JSON
{
  "filters": {
    "must":     [ { "name": "asset_type", "type": "eq", "value": "domain" } ],
    "should":   [ ],
    "must_not": [ { "name": "tags", "type": "in", "value": ["staging"] } ]
  },
  "sort": [ { "field": "added_date", "order": "desc" } ]
}
Part Meaning
must Every filter must match (AND)
should At least one filter must match (OR)
must_not No filter may match (NOT)
sort List of {field, order}; order is asc or desc

A filter is { "name": <field>, "type": <operator>, "value": <value> }. Each search endpoint lists the fields it accepts on its reference page, under Filtering: the searchable fields, grouped by the operators they accept, and the fields sort accepts where the endpoint has them. Unknown fields return 400.

Operators

Operator (type) Value Matches when the field…
eq single value equals the value
in array equals any of the values
startswith / endswith string starts / ends with the value
wildcard string with * / ? matches the pattern
fuzzy string approximately matches the value
contains_any / contains_all array (array field) contains any / all of the values
gte / lte number or date is ≥ / ≤ the value
gt / lt number, date or CVE ID is > / < the value; only in Vulnerability Search of the CVE database (see below)
exists true / false has / has no value

Not every field accepts every operator: see the next section.

Which Operators a Field Accepts

Operator support is set per field. Neither the field's type nor its name tells you which operators it accepts:

  • Text fields of the same endpoint: in Vulnerability Search, the search of the CVE database, id accepts eq, startswith, wildcard, gt, lt and exists, while descriptions.value accepts wildcard, contains_any, contains_all and exists.
  • The same field on different endpoints: asset accepts wildcard and fuzzy in Asset Search, and neither of them in Deleted Asset Search.
  • True/false fields: in Asset Search they accept eq and exists; in Domain Search they accept in as well.
  • Identifiers: id accepts only eq and in in Issue Search.
  • gt and lt: among the searches with must, should and must_not lists, only Vulnerability Search of the CVE database accepts them, on each of its date and number fields and on id. Every other one returns 400 for them (see An Operator the Search Does Not Know), so use gte and lte there. gt and lt do work elsewhere in the API: the searches with another filter format take them as keys of a range filter, and Email Breach List, a list endpoint, as the __gt and __lt suffixes.

So check the field on the endpoint you call. Each search's Filtering section groups its searchable fields by the operators they accept. The groups come from measurement: each operator was sent to each field against the API, and the API's answer decided the field's group. They are not derived from the field's type. A few fields could not be measured: they take a value from a fixed list, the API's error message does not name the values they accept, and the demo account used for the measurement had no records that use them. They are listed under Operators: not measured: website.parent_asset.type in Asset Search, and source_format and network in Compromised Payment Credential Search. Any operator outside a field's group returns 400 (see Filter Errors).

Search Request
Domain Search POST /discovery/domain-search
Vulnerability Search (CVE database) POST /discovery/vulnerability-search
Asset Search POST /easm/assets/search
Deleted Asset Search POST /easm/deleted-assets/search
Discovered Asset Search POST /easm/discovery/assets/search
Issue Search POST /easm/issues/search
Vulnerability Search POST /easm/vulnerabilities/search
Vulnerability Asset Search POST /easm/vulnerabilities/asset-search
Compromised Employee Account Search POST /cti/compromised-employee-accounts/search
Compromised Employee Credential Search POST /cti/compromised-employee-credentials/search
Compromised Client Credential Search POST /cti/compromised-client-credentials/search
Compromised Payment Credential Search POST /cti/compromised-payment-credentials/search
Compromised Device Search POST /cti/compromised-devices
Threat Actor Search POST /cti/threat-actors/search
Security News Search POST /cti/news/search
Fraudulent Domain Search POST /brp/fraudulent-domains/search
Suspicious Domain Search POST /brp/suspicious-domains/search

Exports (…/search:export) and bulk actions (…/search:<action>) have a Filtering section of their own on their reference pages.

Each of these searches, and each export and bulk action beside it, also shows a Request Template among its examples: a request body that lists the endpoint's filters, each with an operator the field accepts and a placeholder value, ready to copy and fill in. A template is a request only; it has no response.

Filter Errors

A filter with an operator the field does not accept returns 400 Bad Request. Today the message comes back in one of three forms, depending on the endpoint. An operator the search does not know at all, such as gt outside Vulnerability Search of the CVE database, returns a fourth:

Form code Message in Message
Invalid query 10400 parameters[].details Invalid query: <field> does not support <operator> query
Supported queries listed 10400 parameters[].details Field '<field>' does not support '<operator>' query. Supported queries are [...]
Not supported yet 30004 details <operator> query type is not supported yet.
Unknown operator 10400 parameters[].details, with param type Select a valid choice.

To catch them all in code, read the messages in both parameters[].details and details: the first three forms say does not support or is not supported, and the unknown operator comes with param set to type.

Invalid Query

Asset Search with startswith on open_port_count, a number field:

400 Bad Request

JSON
{
  "code": 10400,
  "parameters": [
    {
      "param": "must",
      "path": "filters",
      "details": [
        "Invalid query: open_port_count does not support startswith query"
      ]
    }
  ]
}

Supported Queries Listed

Vulnerability Search of the CVE database with gte on id, a text field that accepts gt and lt but not gte:

400 Bad Request

JSON
{
  "code": 10400,
  "parameters": [
    {
      "param": "must",
      "path": "filters",
      "details": [
        "Field 'id' does not support 'gte' query. Supported queries are ['eq', 'exists', 'wildcard', 'startswith', 'lt', 'gt']."
      ]
    }
  ]
}

This form lists the operators the field does accept, which is the quickest way to correct the filter.

Not Supported Yet

Deleted Asset Search with wildcard on asset:

400 Bad Request

JSON
{
  "code": 30004,
  "details": [
    "wildcard query type is not supported yet."
  ]
}

This form names the operator but not the field. Code 30004 also stands for a state change that is not allowed (see Errors), so read the message as well as the code.

An Operator the Search Does Not Know

Asset Search with gt on open_port_count. Among the searches with must, should and must_not lists, only Vulnerability Search of the CVE database knows gt and lt, so here the filter's type itself is rejected:

400 Bad Request

JSON
{
  "code": 10400,
  "parameters": [
    {
      "param": "type",
      "path": "filters.must",
      "details": [
        "Select a valid choice."
      ]
    }
  ],
  "solution": "https://docs.deepinfo.com/reference/"
}

This form names neither the field nor the operator: param is type, and path names the list the filter is in. Use gte or lte instead.

A Value of the Wrong Type

A value of the wrong type for the field also returns 400 with code 10400 and the message in parameters[].details, but it reads differently. Here the operator is accepted and the value is not:

400 Bad Request

JSON
{
  "code": 10400,
  "parameters": [
    {
      "param": "must",
      "path": "filters",
      "details": [
        "Invalid value true: $eq must be boolean."
      ]
    }
  ]
}

The message names the value you sent, the operator and the type the field needs: boolean here, numeric for a number field. Keep the operator and send the value as that type.

Always Send a Filter

An empty body {} matches everything. For bulk actions (delete, tag, state changes) that means every record.

Warning

Always send a filter with a bulk action. An empty body {} applies the action to every record.

A Complete Request

Shell
curl -X POST "https://api.deepinfo.com/v1/easm/assets/search" \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "must": [ { "name": "asset_type", "type": "eq", "value": "domain" } ]
    },
    "sort": [ { "field": "added_date", "order": "desc" } ]
  }'

See Asset Search for the fields this endpoint accepts.

Results and Exports

Search results are paginated: see Pagination. The matching …/search:export endpoints return the matches as CSV or a JSON array (format query parameter), for example Asset Export. Large exports can time out, so narrow them with filters too.

Searches With Another Filter Format

A few searches take filters as an object with one key per field instead of must, should and must_not lists. Each field takes its operators as keys, the fields combine with AND, and sort is one {field, order} object instead of a list. For example, Technology Search:

JSON
{
  "filters": {
    "technology": { "equals": "nginx" }
  },
  "sort": { "field": "technology", "order": "desc" }
}

A number or date field takes a range filter, with gt, gte, lt and lte as its keys. Technologies found on more than five of your assets:

JSON
{
  "filters": {
    "affected_asset_count": { "gt": 5 }
  }
}

These searches use this format. The Filtering section of each one lists its fields and the operators each field takes:

Search Request
Technology Search POST /easm/technologies/search
Technology Asset Search POST /easm/technologies/asset-search
Asset Discovery Custom Discovery Rule Search POST /easm/discovery/custom-rules/search
Fraudulent Rule Search POST /brp/fraudulent-rules/search
Report Search POST /platform/reports/search

The exports of the technology searches take the same format. Report Search also requires filters.type, for example:

JSON
{
  "filters": {
    "type": "easm_executive_summary"
  }
}

List Endpoints

List endpoints (GET) filter with query parameters instead, for example:

Text
?email__contains=john&vip=true&ordering=-last_breach_date

The suffix sets the operator (__contains, __not_contains, __icontains, __startswith, __in, __nin, __gte, __lte, __gt, __lt), and ordering sorts (prefix - for descending). Each list endpoint's reference page shows the query parameters it accepts. Not every list endpoint takes every suffix: Email Breach List takes __gt and __lt on its dates and counts, while Breached Account List, Notification Email List, Notification Rule List and Scheduled Report Rule List take __gte and __lte. The other list endpoints have no range suffix.

Last updated