Search & Filters
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):
{
"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,
idacceptseq,startswith,wildcard,gt,ltandexists, whiledescriptions.valueacceptswildcard,contains_any,contains_allandexists. - The same field on different endpoints:
assetacceptswildcardandfuzzyin Asset Search, and neither of them in Deleted Asset Search. - True/false fields: in Asset Search they accept
eqandexists; in Domain Search they acceptinas well. - Identifiers:
idaccepts onlyeqandinin Issue Search. gtandlt: among the searches withmust,shouldandmust_notlists, only Vulnerability Search of the CVE database accepts them, on each of its date and number fields and onid. Every other one returns 400 for them (see An Operator the Search Does Not Know), so usegteandltethere.gtandltdo 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__gtand__ltsuffixes.
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
{
"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
{
"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
{
"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
{
"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
{
"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
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:
{
"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:
{
"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:
{
"filters": {
"type": "easm_executive_summary"
}
}
List Endpoints
List endpoints (GET) filter with query parameters instead, for example:
?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.