List a brand's domains
const url = 'https://app.nebty.de/core/api/brands/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/domains/?group_by=apex&http_status_filter=all&risk_score_filter=all&sort_direction=asc&sort_field=domain&triage_filter=all&verdict_filter=all&visual_match_filter=all';const options = {method: 'GET', headers: {Authorization: '<Authorization>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://app.nebty.de/core/api/brands/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/domains/?group_by=apex&http_status_filter=all&risk_score_filter=all&sort_direction=asc&sort_field=domain&triage_filter=all&verdict_filter=all&visual_match_filter=all' \ --header 'Authorization: <Authorization>'Returns the domains associated with a brand, with filtering and sorting. risk_score and verdict describe the pairing of this brand with the domain, not the domain on its own. The default order is highest risk first.
Paginated: page and page_size (default 50, maximum 100). See the pagination note in the API description.
Use compact=true for a short row per domain (id, name, source, a compact latest_scan and open_takedown). Without it every row embeds scan history and is much larger; fetch a single domain when you need the evidence.
Filters: domain_filter (case-insensitive substring of the name), http_status_filter (online, offline, all), risk_score_filter (low, medium, high, all), verdict_filter (red, amber, green, unknown, all) and triage_filter. visual_match_filter is deprecated; use verdict_filter. Sort with sort_field and sort_direction. group_by=apex returns one row per registrable domain, with its subdomains collapsed, instead of one row per domain. An unsupported group_by or triage_filter value is rejected with 400.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”UUID of the brand, as returned in the id field of the brand list.
Query Parameters
Section titled “Query Parameters”Return compact list summaries without embedded history. Use domain detail for evidence.
Filter domains by name (case-insensitive substring match)
Collapse the list to one row per registrable apex (eTLD+1) so a third-party domain and all its subdomains take one decision. Applied after every filter. With ‘apex’ the response items are BrandDomainApexGroup objects, not Domain objects, and the paginated count is the number of apexes — summing domain_count over all pages reproduces the ungrouped total for the same filter. Default ‘none’.
Filter by HTTP status: ‘online’, ‘offline’, or ‘all’
Page number within the paginated result set.
Rows per page. Defaults to 50; clamped to 100 above that.
Filter by risk score level: ‘low’, ‘medium’, ‘high’, or ‘all’
Sort direction
Field to sort by. ‘review_priority’ is the layer-2 pre-ranking of what a human still has to review; unranked pairs sort below every ranked one, with risk breaking ties. Under group_by=apex only ‘domain’ (apex name) and ‘risk_score’ (the group’s worst host) apply.
Filter by the common-word triage outcome, for brands where it is enabled. ‘queue’ hides the pairs the machine filed as an unrelated entity or a name collision — the review worklist. ‘filed’ shows only those, for auditing what was hidden. ‘escalated’ shows only pairs carrying a brand-affinity token. Pairs a human has judged are never hidden by this filter and never listed as machine decisions. Default ‘all’, which returns every row. Note that the brand statistics endpoints (/stats/ and ?include_stats=true) always describe the ‘queue’ population, so verdict_stats matches the row count under ‘queue’ rather than under ‘all’.
Filter by the merged customer-facing verdict for this brand’s pair with the domain. Accepts the same values as BrandStatsSerializer.verdict_stats’ keys, plus ‘all’ — a stat and its filtered list can never disagree.
DEPRECATED — use verdict_filter. Filter by visual match: ‘yes’, ‘no’, ‘unknown’, or ‘all’. Kept so the frontend does not break on deploy; the visual scan is now one of two inputs to the merged verdict, not the customer-facing answer.
Responses
Section titled “Responses”object
Serializer for Domain model.
object
How this domain was discovered/added to the system
VARIATION- Generated from VariationCERTSTREAM- CertStream APISUBDOMAIN_SCAN- Subdomain ScanMANUAL- Manual EntryAD_LIBRARY- Meta Ad Library
object
The single customer-facing verdict, resolved for the requesting brand.
Unlike risk_score/visual_match there is no shared DomainScan
column to fall back to: the merged verdict has only ever lived on the
pair (BrandDomainAssociation.refresh_merged_verdict), so a caller
with no brand in context — or a historical scan row, which carries no
pair-specific verdict of its own — gets “unknown” rather than another
brand’s answer.
When this brand last had the domain visually scanned.
The shared timestamp is whichever brand scanned the domain most recently, so on a shared hostname it is somebody else’s. NULL on the pair means this brand has not scanned it yet, which is exactly what the cooldown treats it as.
URL to the screenshot of the domain stored in Hetzner S3-compatible Object Storage
Whether this brand still has an unsent alert for the domain.
The shared flag means “somebody has one”, so after this brand’s alert was sent it would keep reporting true while another brand’s is pending.
A completeness of 0 means that the domain has no records set. The higher this number, the more likely the domain is actually used.
The domain’s scan timeline, most recent first.
On a domain that has only ever had single-brand history, the whole history is this brand’s own and renders untouched. Once branded rows exist, the domain has had a multi-brand period: the requesting brand then sees only its own rows, and NULL-brand rows are redacted because current association count can no longer prove which brand they belonged to.
object
Free text comment from the user.
User who submitted the feedback.
When the feedback was submitted.
Serializer for DomainScan model.
risk_score and visual_match are answers about a brand↔domain pair,
not about the domain (#954). When the caller puts a brand in the
serializer context — every brand-scoped endpoint does — both are rendered
from that brand’s association, so a domain two customers monitor shows each
of them the verdict computed against their own brand.
Without a brand in context the shared columns are rendered unchanged, which
is what the domain-global endpoints and the admin want. That column now
means “the worst score across every brand monitoring this domain” rather
than “the longest-monitored brand’s score” — see
DomainScan.get_risk_score.
verdict/verdict_reasoning/requires_human_review are the single
customer-facing verdict merged from the visual and content detectors
(BrandDomainAssociation.refresh_merged_verdict) and are what the
frontend should read going forward. visual_match is kept in the payload
as deprecated — do not remove it — because it still governs code paths
mid-migration; new consumers should read verdict instead.
object
The single customer-facing verdict, resolved for the requesting brand.
Unlike risk_score/visual_match there is no shared DomainScan
column to fall back to: the merged verdict has only ever lived on the
pair (BrandDomainAssociation.refresh_merged_verdict), so a caller
with no brand in context — or a historical scan row, which carries no
pair-specific verdict of its own — gets “unknown” rather than another
brand’s answer.
When this brand last had the domain visually scanned.
The shared timestamp is whichever brand scanned the domain most recently, so on a shared hostname it is somebody else’s. NULL on the pair means this brand has not scanned it yet, which is exactly what the cooldown treats it as.
URL to the screenshot of the domain stored in Hetzner S3-compatible Object Storage
Whether this brand still has an unsent alert for the domain.
The shared flag means “somebody has one”, so after this brand’s alert was sent it would keep reporting true while another brand’s is pending.
A completeness of 0 means that the domain has no records set. The higher this number, the more likely the domain is actually used.
The domain’s scan timeline, most recent first.
On a domain that has only ever had single-brand history, the whole history is this brand’s own and renders untouched. Once branded rows exist, the domain has had a multi-brand period: the requesting brand then sees only its own rows, and NULL-brand rows are redacted because current association count can no longer prove which brand they belonged to.
object
Free text comment from the user.
User who submitted the feedback.
When the feedback was submitted.
object
Takedown id; fetch the case at GET /core/api/takedowns/{id}/.
Current status of the running case.
REQUESTED- Requested (Pending Approval)OPEN- OpenIN_PROGRESS- In ProgressPENDING_RESPONSE- Pending ResponseCLOSED- ClosedFAILED- FailedREJECTED- Rejected
object
Takedown id; fetch the case at GET /core/api/takedowns/{id}/.
How the case ended: CLOSED (worked to a conclusion, see resolution) or FAILED (abandoned, no resolution).
CLOSED- ClosedFAILED- Failed
DOMAIN_SUSPENDED- Domain SuspendedCONTENT_REMOVED- Content RemovedSERVER_HOLD- Server HoldVOLUNTARY_TAKEDOWN- Voluntary TakedownUNRESOLVED- UnresolvedFALSE_POSITIVE- False Positive
Outcome of a CLOSED case. FALSE_POSITIVE means the analysts found no infringement. Null for FAILED, and for a CLOSED case that was closed without a resolution.
DOMAIN_SUSPENDED- Domain SuspendedCONTENT_REMOVED- Content RemovedSERVER_HOLD- Server HoldVOLUNTARY_TAKEDOWN- Voluntary TakedownUNRESOLVED- UnresolvedFALSE_POSITIVE- False Positive
When the case finished. For CLOSED this is the case’s closed_at; FAILED and undated legacy cases use a stable result timestamp.
Serializer for Domain model.
object
How this domain was discovered/added to the system
VARIATION- Generated from VariationCERTSTREAM- CertStream APISUBDOMAIN_SCAN- Subdomain ScanMANUAL- Manual EntryAD_LIBRARY- Meta Ad Library
object
The single customer-facing verdict, resolved for the requesting brand.
Unlike risk_score/visual_match there is no shared DomainScan
column to fall back to: the merged verdict has only ever lived on the
pair (BrandDomainAssociation.refresh_merged_verdict), so a caller
with no brand in context — or a historical scan row, which carries no
pair-specific verdict of its own — gets “unknown” rather than another
brand’s answer.
object
Takedown id; fetch the case at GET /core/api/takedowns/{id}/.
Current status of the running case.
REQUESTED- Requested (Pending Approval)OPEN- OpenIN_PROGRESS- In ProgressPENDING_RESPONSE- Pending ResponseCLOSED- ClosedFAILED- FailedREJECTED- Rejected
object
Takedown id; fetch the case at GET /core/api/takedowns/{id}/.
How the case ended: CLOSED (worked to a conclusion, see resolution) or FAILED (abandoned, no resolution).
CLOSED- ClosedFAILED- Failed
DOMAIN_SUSPENDED- Domain SuspendedCONTENT_REMOVED- Content RemovedSERVER_HOLD- Server HoldVOLUNTARY_TAKEDOWN- Voluntary TakedownUNRESOLVED- UnresolvedFALSE_POSITIVE- False Positive
Outcome of a CLOSED case. FALSE_POSITIVE means the analysts found no infringement. Null for FAILED, and for a CLOSED case that was closed without a resolution.
DOMAIN_SUSPENDED- Domain SuspendedCONTENT_REMOVED- Content RemovedSERVER_HOLD- Server HoldVOLUNTARY_TAKEDOWN- Voluntary TakedownUNRESOLVED- UnresolvedFALSE_POSITIVE- False Positive
When the case finished. For CLOSED this is the case’s closed_at; FAILED and undated legacy cases use a stable result timestamp.
One row of the apex-grouped brand domain list (?group_by=apex).
Not a ModelSerializer: a row is an aggregate over many Domains, not one of
them. registrable_apex falls back to the hostname for rows whose apex
column is unset, so every domain is represented in exactly one group and
the domain_count values sum to the ungrouped row count.
object
Registrable apex (eTLD+1) shared by every host in this group.
How many hostnames in this brand’s list share this apex.
Highest pair risk score among the group’s hosts. The worst host decides the group, so collapsing rows can never lower a score.
Example
{ "count": 123, "next": "http://api.example.org/accounts/?page=4", "previous": "http://api.example.org/accounts/?page=2", "results": [ { "source": "VARIATION", "latest_scan": { "user_feedback_type": "false_positive" }, "scans": [ { "user_feedback_type": "false_positive" } ], "open_takedown": { "status": "REQUESTED" }, "last_closed_takedown": { "status": "CLOSED", "resolution": "DOMAIN_SUSPENDED" } } ]}Invalid query parameters or request data. Field errors appear directly on the response; malformed JSON has a detail message.
object
Field names mapped directly to validation error messages.
object
Example
{ "target_website": [ "Target host is not a public address." ]}The API key is missing, invalid, revoked or belongs to an inactive user.
object
Examplegenerated
{ "detail": "example"}The requested page or record does not exist or cannot be accessed.
object
Examplegenerated
{ "detail": "example"}Too many requests or failed authentication attempts. Try again later.
object
Examplegenerated
{ "detail": "example"}