Download OpenAPI specification:
API for submitting and querying malicious URLs, managing false positives, and accessing WHOIS data.
To use this API, you must obtain an API key (called a token) by registering at: https://threatcenter.crdf.fr/api.html
Conventional CRDF API methods use HTTP POST with Content-Type: application/json.
The STIX 2.1 exports and TAXII 2.1 resources documented below use HTTP GET
with Bearer authentication and their standard media types. All of these CTI
resources, including TAXII discovery, are reserved for licensed private accounts.
Modern approach (recommended): Use the Authorization header:
curl -X POST https://threatcenter.crdf.fr/api/v1/info_key.json \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key_here" \
-d '{
"method": "info_key"
}'
Alternative: You can also use the X-API-Key header:
curl -X POST https://threatcenter.crdf.fr/api/v1/info_key.json \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"method": "info_key"
}'
Legacy (deprecated): For backward compatibility, the token can still be sent in the request body:
curl -X POST https://threatcenter.crdf.fr/api/v1/info_key.json \
-H "Content-Type: application/json" \
-d '{
"token": "your_api_key_here",
"method": "info_key"
}'
Conventional POST API responses follow this standard format. Native STIX exports and TAXII resources instead follow their respective standards:
Success Response:
{
"error": false,
"error_code": null,
"message": null,
"data": { ... }
}
Error Response:
{
"error": true,
"error_code": "ErrorCode",
"message": "Human-readable error message",
"data": null
}
error field firsterror_code for programmatic error handlingRetry-After response header and implement exponential backoffThis is API version 1.4.3. The API follows semantic versioning:
The current version is stable. Breaking changes will be announced in advance and documented in the Changelog.
For the latest changes, see: CHANGELOG.md
The API implements multiple layers of security protection to ensure service availability and prevent abuse:
To ensure secure and reliable API usage, follow these best practices:
error field in API responses before processing dataerror_code for programmatic error handling (don't rely on message text)Effective limits may be customized per API key. The defaults below document the production safety policy:
| Endpoint group | Endpoint(s) | Default limit |
|---|---|---|
| AI search | ai_search_domain, ai_search_ioc |
180/min, 5,000/hour, 100,000/day |
| AI bulk search | ai_search_bulk |
60/min, 1,000/hour, 10,000/day |
| AI queue status | ai_status_ioc |
240/min, 8,000/hour, 150,000/day |
| AI profile/list | ai_profile_ioc, ai_list_entries |
60-120/min depending on endpoint |
| AI scoring | ai_score_domain, ai_score_ioc |
30/min, 600/hour, 5,000/day |
| AI bulk scoring | ai_score_bulk |
10/min, 150/hour, 1,500/day |
| AI export | ai_export_delta |
10/min, 120/hour, 1,000/day |
| STIX / TAXII CTI read | cti_export_*, taxii_objects, taxii_manifest |
30/min, 500/hour, 5,000/day |
| URL submission | submit_url, add_urls |
20-30/min depending on endpoint |
| WHOIS / NRD / URL lists | whois_*, get_nrd, list_malicious_domains |
endpoint-specific read quotas |
If an endpoint-specific limit is exceeded, the API returns 429 EndpointRateLimitExceeded.
The API records security metadata for sensitive calls. Payloads are not logged verbatim; a SHA-256 payload hash and request size are retained for audit and abuse detection.
The following patterns may be flagged:
ai_score_* usageai_export_delta usageAnomaly events are used for operational review, throttling decisions and abuse investigation. They do not change endpoint response schemas.
Public API error responses are intentionally sanitized. They do not expose SQL, filesystem paths, stack traces, model thresholds, registry paths, internal calibration details, or raw secrets. Use error_code for client logic; do not depend on the exact human-readable message.
AI endpoints expose public-safe verdict, category, score, queue state and evidence summaries. They do not expose SQL row identifiers, raw component scores, private thresholds, calibration details, model registry paths or internal request IDs. Queue polling uses an opaque job_ref when a public reference is useful.
API keys expose modern scopes in the permissions field returned by info_key.json.
The legacy special_methods_allowed string is still returned for backward compatibility.
Access levels:
| Access level | Typical scopes | Result |
|---|---|---|
| Free validated API key | none or public actions only |
Public submission and tracking only; no private CTI data |
| Private licensed account | unlimited, private, lookup, feeds, AI, WHOIS, NRD |
Contractual private CTI access |
| Redistribution license | Private licensed scopes plus redistribution |
Redistribution only within written approval |
| CRDF internal | Operational scopes, optionally urls:add |
Direct database curation and internal maintenance |
urls:add and its legacy alias add_urls are not customer-license scopes. They are reserved for CRDF internal operations.
| Scope | Description |
|---|---|
lookup |
Search URLs against CRDF Threat Center data |
feeds:domains |
Retrieve malicious domain feeds |
feeds:urls |
Reserved for malicious URL feeds |
feeds:ips |
Reserved for malicious IP feeds |
ai:score |
Score domains, URLs or IPs with the CRDF AI engine |
ai:search |
Search AI results and retrieve AI status/profile data |
ai:list |
List or export already scored AI entries |
cti:ai |
Export the CRDF AI collection as STIX 2.1 |
cti:url-telemetry |
Export the CRDF URL Telemetry collection as STIX 2.1 |
taxii:read |
Discover and synchronize authorized collections using TAXII 2.1 |
whois |
Retrieve WHOIS enrichment data |
nrd |
Retrieve Newly Registered Domains |
urls:add |
Add URLs directly to the threat database |
urls:add:permanent |
Mark directly inserted URLs as permanent |
urls:add:bypass-timeout |
Bypass the recent-removal timeout during direct insertion |
false_positive:auto_accept |
Auto-accept a false-positive deletion request when requested |
redistribution |
Redistribution has been explicitly approved in writing |
Legacy permissions are mapped automatically:
| Legacy permission | Modern scope mapping |
|---|---|
private |
Licensed lookup/feed/AI scopes plus cti:ai, cti:url-telemetry and taxii:read |
add_urls |
urls:add, urls:add:permanent, urls:add:bypass-timeout |
fp_force_deleted |
false_positive:auto_accept |
unlimited |
Usage flag only; disables key-level throttling but does not grant data access by itself |
| Endpoint | Required Permissions | Optional Permissions |
|---|---|---|
info_key.json |
None | - |
submit_url.json |
None | - |
submit_get_info.json |
None | - |
search_urls.json |
lookup |
- |
ai_score_domain.json |
ai:score |
- |
ai_search_domain.json |
ai:search |
- |
ai_score_ioc.json |
ai:score |
URL, domain name or IP address |
ai_search_ioc.json |
ai:search |
URL, domain name or IP address |
ai_status_ioc.json |
ai:search |
URL, domain name or IP address |
ai_profile_ioc.json |
ai:search |
URL, domain name or IP address |
ai_score_bulk.json |
ai:score |
Up to 100 URL/domain/IP IOCs |
ai_search_bulk.json |
ai:search |
Up to 500 URL/domain/IP IOCs |
ai_export_delta.json |
ai:list |
Incremental v14 AI export |
ai_list_entries.json |
ai:list |
- |
add_urls.json |
urls:add |
urls:add:permanent, urls:add:bypass-timeout |
false_positive_ng.json |
None | false_positive:auto_accept (for auto-acceptance) |
false_positive_getinfos.json |
None | - |
whois_get.json |
whois |
- |
whois_list_domains.json |
whois |
- |
get_nrd.json |
nrd |
- |
list_malicious_domains.json |
feeds:domains |
- |
GET /cti/stix/crdf-ai |
private plus cti:ai |
Native STIX 2.1 export for licensed private accounts |
GET /cti/stix/url-telemetry |
private plus cti:url-telemetry |
Native STIX 2.1 export for licensed private accounts |
GET /api/taxii2/... |
private, taxii:read, plus the collection scope when applicable |
TAXII 2.1 discovery and read-only synchronization for licensed private accounts |
Submission and false-positive references are scoped to the API key that created them. They are opaque tracking values and should not be treated as shared identifiers between clients.
References returned by the API follow this format:
YYYYMMDD + strong random suffix20260418a1b2c3d4e5f620260418 = Datea1b2c3d4e5f6 = Opaque random suffix for uniquenesssubmit_url, false_positive_ngSeveral endpoints use cursor-based pagination for efficient data retrieval:
cursor: 0 to start from the beginningnext_cursor with the ID of the last returned recordnext_cursor value as the new cursornext_cursor is null, you've reached the end// Request 1
{ "cursor": 0, "per_page": 100 }
// Response: { "data": [...], "next_cursor": 100 }
// Request 2
{ "cursor": 100, "per_page": 100 }
// Response: { "data": [...], "next_cursor": 200 }
// Request 3
{ "cursor": 200, "per_page": 100 }
// Response: { "data": [...], "next_cursor": null } // End reached
whois_list_domains.json - Cursor: ID_DOMAINget_nrd.json - Cursor: NRD IDlist_malicious_domains.json - Cursor: Record IDsubmit_get_info)| State | Description |
|---|---|
new |
Submission received, not yet processed |
processing |
Currently being analyzed by experts |
end |
Processing completed |
urls_arr)| State | Description |
|---|---|
accepted |
URL was accepted and added to database |
rejected |
URL was rejected (e.g., whitelisted, invalid) |
pending |
Still being processed |
error |
An error occurred during processing |
| Verdict | Description |
|---|---|
whitelisted |
URL is on the whitelist |
malicious |
Confirmed as malicious |
suspicious |
Suspicious but not confirmed |
clean |
Determined to be clean |
deleted |
False positive, removed from database |
| Status | Description |
|---|---|
new |
Request submitted, awaiting review |
reviewing |
Under expert review |
finished |
Review completed |
| Verdict | Description |
|---|---|
deleted |
URL was removed from blacklist |
rejected |
Request was rejected |
pending |
Still pending |
The following errors can be returned by any endpoint. Each error response follows the standard format:
{
"error": true,
"error_code": "ErrorCode",
"message": "Human-readable error message",
"data": null
}
| Error Code | HTTP Status | Description |
|---|---|---|
InvalidContentType |
415 | The request's Content-Type header is not application/json |
InvalidInputJson |
400 | The request body is not valid JSON |
InvalidRequestType |
405 | The HTTP method is not allowed (only POST is accepted) |
InvalidMethod |
400 | The method field does not match any supported endpoint |
InvalidToken |
401 | The provided API key does not exist or is not active |
MissingPermission |
403 | The API key is valid but does not grant the required scope |
RequestExceed |
429 | Rate limit exceeded for this API key (per-minute or daily quota) |
EndpointRateLimitExceeded |
429 | Rate limit exceeded for this specific endpoint |
IPBlacklisted |
429 | The client IP has been temporarily blocked due to burst detection |
KeyBlacklisted |
429 | The API key has been temporarily blocked due to abuse |
IPRateLimitExceeded |
429 | The IP address has exceeded global rate limits (across all tokens) |
DistributedAttackDetected |
429 | Suspicious activity detected: token used from multiple IPs simultaneously |
RequestBodyTooLarge |
413 | The request body exceeds the maximum allowed size (10MB) |
ArraySizeExceeded |
400 | An array in the request exceeds the maximum allowed size (10,000 elements default) |
InvalidRequest |
400 | A required JSON parameter is missing or malformed |
InternalError |
500 | An internal error occurred |
NotImplemented |
501 | The requested method is not implemented |
InvalidToken: The API key provided does not exist, is inactive, or has been revoked.info_key endpoint.MissingPermission: The API key is valid, but the requested endpoint requires a scope that the key does not have.info_key.json and inspect permissions before calling private endpoints.data.required_permission, data.granted_permissions, and data.compat_error_code.Multiple rate limiting mechanisms can trigger 429 errors:
RequestExceed: Token-level rate limit exceeded (per-minute or daily quota)
EndpointRateLimitExceeded: Endpoint-specific rate limit exceeded
ai_score_* and ai_export_delta have stricter limits than read-only search endpointsIPBlacklisted: IP address temporarily blocked due to burst detection
KeyBlacklisted: API key temporarily blocked due to abuse
IPRateLimitExceeded: IP-level rate limit exceeded (across all tokens)
DistributedAttackDetected: Suspicious activity detected: token used from multiple IPs simultaneously
InvalidInputJson: JSON parsing failed
InvalidMethod: Unknown method name
InvalidRequest: Missing required parameters
token, method, etc.) are presentArraySizeExceeded: Array too large
RequestBodyTooLarge: Request body exceeds maximum sizeInternalError: Internal server error
NotImplemented: Method not implemented
error field first in the responseerror_code for programmatic error handling (don't rely on message text)For detailed information about changes, new features, and deprecations, see: CHANGELOG.md
Retrieve metadata about the API key including rate limits, usage statistics, and permissions.
This endpoint is public (no permission required).
| token | string Your API key |
| method required | string Value: "info_key" |
{- "token": "your_api_key_here",
- "method": "info_key"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "msg": "Data found",
- "company_or_name": "CRDF Labs",
- "requests_peer_minute": 10,
- "requests_peer_day": 200,
- "current_request_day": 171,
- "current_request_minute": 0,
- "usage_observed_at": 1788105600,
- "usage_source": "detailed_events",
- "usage_windows": {
- "minute": {
- "used": 0,
- "limit": null,
- "remaining": null,
- "window_seconds": 60,
- "resets_at": 1788105660
}, - "day": {
- "used": 171,
- "limit": null,
- "remaining": null,
- "window_seconds": 86400,
- "resets_at": 1788192000
}
}, - "endpoint_rate_limits": {
- "submit_url": {
- "minute": 30,
- "hour": 500,
- "day": 5000
}
}, - "last_access_timestamp": 1739040000,
- "last_access_ip": "122.11.11.21",
- "plan": "pro",
- "license_terms": "contractual_private_use",
- "private_access": true,
- "redistribution_allowed": false,
- "permissions": [
- "lookup",
- "feeds:domains",
- "feeds:urls",
- "feeds:ips",
- "ai:score",
- "ai:search",
- "ai:list",
- "cti:ai",
- "cti:url-telemetry",
- "taxii:read",
- "whois",
- "nrd"
], - "permission_details": {
- "legacy": [
- "private",
- "unlimited"
], - "scopes": [
- "lookup",
- "feeds:domains",
- "feeds:urls",
- "feeds:ips",
- "ai:score",
- "ai:search",
- "ai:list",
- "cti:ai",
- "cti:url-telemetry",
- "taxii:read",
- "whois",
- "nrd"
], - "flags": [
- "unlimited"
]
}, - "usage_rights": {
- "plan": "pro",
- "license_terms": "contractual_private_use",
- "public_api_access": true,
- "private_access": true,
- "redistribution_allowed": false,
- "commercial_use": "governed_by_contract",
- "cti_exchange": "governed_by_contract"
}, - "special_methods_allowed": "unlimited,private"
}
}Submit malicious URLs for expert analysis. Maximum 250 unique URLs per request.
This endpoint is public (no permission required).
| Idempotency-Key | string [ 8 .. 128 ] characters ^[A-Za-z0-9._:-]{8,128}$ Stable client-generated key used to safely retry the same URL set without creating a duplicate submission.
Reusing a key with a different URL set returns |
| token | string Your API key |
| method required | string Value: "submit_url" |
| urls required | Array of strings <uri> [ 1 .. 250 ] items [ items <uri > [ 3 .. 10000 ] characters ] Array of malicious URLs to submit (maximum 250 unique URLs, each URL must be 3-10000 characters) |
{- "token": "your_api_key",
- "method": "submit_url",
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "msg": "Malicious URLs received and accepted into the analysis queue. Use the reference to follow processing status.",
- "ref": "202506011234567890",
- "idempotent_replay": false
}
}Retrieve status and details for a previously submitted set of URLs.
This endpoint is public (no permission required). A reference is only visible to the API key that created the submission.
| token | string Your API key |
| method required | string Value: "submit_get_info" |
| ref required | string^[A-Za-z0-9]+$ Opaque alphanumeric reference returned by submit_url |
{- "token": "your_api_key",
- "method": "submit_get_info",
- "ref": "20260723a1b2c3d4e5f6"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "msg": "Data found",
- "ref": "202506011234567890",
- "timestamp": 1739040000,
- "state": true,
- "urls_added": [ ],
- "urls_arr": [
- {
- "domain_name": "example.com",
- "state": "rejected",
- "verdict": "whitelisted",
- "description": "URL state values: accepted, rejected, pending, error\nVerdict values: whitelisted, malicious, suspicious, clean, deleted\n"
}
], - "urls_accepted": 0,
- "urls_rejected": 1,
- "urls_error": 0,
- "urls_total": 1
}
}Check a list of URLs against the blacklisted database.
Required Permission: lookup
| token | string Your API key |
| method required | string Value: "search_urls" |
| urls required | Array of strings List of URLs to check |
{- "token": "your_api_key",
- "method": "search_urls",
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": [
- {
- "error": false,
- "message": "Unknown URL in database.",
- "in_database": false
}, - {
- "error": false,
- "message": "",
- "in_database": true,
- "data": {
- "ID": "29532474",
- "domainName": "vickychaudhry.com",
- "category": "Malicious:URL",
- "timeAdded": "1664539203",
- "isBlacklisted": "1",
- "isAdvert": "0",
- "permanent": "0"
}
}
]
}Add malicious URLs to the database. Maximum 10,000 URLs per request.
Required Permission: urls:add
Setting permanent additionally requires urls:add:permanent. Setting
bypass_timeout additionally requires urls:add:bypass-timeout. Legacy
CRDF-managed keys carrying add_urls retain both capabilities.
| token | string Your API key |
| method required | string Value: "add_urls" |
| urls required | Array of strings [ 1 .. 10000 ] items [ items [ 1 .. 10000 ] characters ] Array of URLs to add (maximum 10000 URLs) |
| category | string Threat category (default "Malicious:URL") |
| bypass_timeout | integer Enum: 0 1 If 1, ignore recent unblacklist timeout (requires |
| advert | integer Enum: 0 1 If 1, mark as advertisement |
| permanent | integer Enum: 0 1 If 1, URL cannot be removed by false positive system (requires |
{- "token": "your_api_key",
- "method": "add_urls",
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": [
- {
- "url": "perdu.com",
- "message": "URL cannot be added because it is whitelisted."
}, - {
- "url": "perdus.com",
- "message": "This URL has been added to the database."
}
]
}List malicious domain names contained in the database with cursor-based pagination.
Required Permission: feeds:domains
| token | string Your API key |
| method required | string Value: "list_malicious_domains" |
| cursor | integer >= 0 Default: 0 Last-seen record ID (exclusive). Use 0 to start from the first record. Pagination: See pagination documentation in |
| per_page | integer [ 1 .. 500 ] Default: 100 Number of records to return per page (max 500) |
{- "token": "your_api_key",
- "method": "list_malicious_domains",
- "cursor": 0,
- "per_page": 100
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "domains": [
- {
- "ID": 50812589,
- "domainName": "eastlink-100615.weeblysite.com",
- "category": "Malicious:URL",
- "timeAdded": 1745270444,
- "isBlacklisted": true
}, - {
- "ID": 50812590,
- "domainName": "cpanel.website-4de3e3a4.tcl.icz.temporary.site",
- "category": "Malicious:URL",
- "timeAdded": 1745270444,
- "isBlacklisted": true
}
], - "next_cursor": 50812590
}
}Submit a domain name to the AI engine and return the latest available AI result.
If the domain is newly queued or currently being processed, the response returns a processing state.
Required Permission: ai:score
| token | string Your API key |
| method required | string Value: "ai_score_domain" |
| domain_name required | string Domain name to score |
{- "token": "your_api_key",
- "method": "ai_score_domain",
- "domain_name": "example.com"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "domain_name": "example.com",
- "status": "done",
- "processing": false,
- "result": {
- "ioc": "example.com",
- "verdict": "safe",
- "score": 0.12,
- "timestamp_created": 1776530000,
- "timestamp_updated": 1776530200,
- "scanned": "yes",
- "priority": "high",
- "mode": "primary",
- "risk_band": "safe",
- "risk_score": 0.12,
- "risk_score_10": 1.2,
- "ml_label": "safe",
- "ml_score": 0.08,
- "primary_category": "Legitimate",
- "primary_category_group": "General",
- "primary_category_confidence": 0.96,
- "primary_taxonomy_version": "crdf-security-category-v14",
- "secondary_category_safe": "Unrated/Unknown",
- "secondary_category_safe_family": "Background/Unknown",
- "secondary_category_safe_confidence": 0.82,
- "secondary_category_safe_source": "safe_abstain",
- "secondary_category_decision": "General/Other",
- "secondary_category_decision_family": "Background/Unknown",
- "secondary_category_decision_confidence": 0.74,
- "secondary_category_decision_source": "fallback_non_security",
- "secondary_category_decision_legacy": "Unrated",
- "secondary_category_taxonomy_version": "crdf-secondary-openworld-v14",
- "secondary_category_evidence": [ ],
- "secondary_category_safe_evidence": [ ],
- "secondary_openworld_scored_at": 1776530200,
- "top_related_score": 0,
- "factor_count": 5,
- "model_version": "domain.v14.model@local",
- "schema_version": "crdf-v14-domain-1",
- "service_mode": "primary",
- "captured_at": 1776530200
}
}
}Retrieve the latest scored AI entry for a single domain name.
Required Permission: ai:search
| token | string Your API key |
| method required | string Value: "ai_search_domain" |
| domain_name required | string Domain name to search |
{- "token": "your_api_key",
- "method": "ai_search_domain",
- "domain_name": "example.com"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "domain_name": "example.com",
- "result": {
- "ioc": "example.com",
- "verdict": "safe",
- "score": 0.12,
- "timestamp_created": 1776530000,
- "timestamp_updated": 1776530200,
- "scanned": "yes",
- "priority": "high",
- "mode": "primary",
- "risk_band": "safe",
- "risk_score": 0.12,
- "risk_score_10": 1.2,
- "ml_label": "safe",
- "ml_score": 0.08,
- "primary_category": "Legitimate",
- "primary_category_group": "General",
- "primary_category_confidence": 0.96,
- "primary_taxonomy_version": "crdf-security-category-v14",
- "secondary_category_safe": "Unrated/Unknown",
- "secondary_category_safe_family": "Background/Unknown",
- "secondary_category_safe_confidence": 0.82,
- "secondary_category_safe_source": "safe_abstain",
- "secondary_category_decision": "General/Other",
- "secondary_category_decision_family": "Background/Unknown",
- "secondary_category_decision_confidence": 0.74,
- "secondary_category_decision_source": "fallback_non_security",
- "secondary_category_decision_legacy": "Unrated",
- "secondary_category_taxonomy_version": "crdf-secondary-openworld-v14",
- "secondary_category_evidence": [ ],
- "secondary_category_safe_evidence": [ ],
- "secondary_openworld_scored_at": 1776530200,
- "top_related_score": 0,
- "factor_count": 5,
- "model_version": "domain.v14.model@local",
- "schema_version": "crdf-v14-domain-1",
- "service_mode": "primary",
- "captured_at": 1776530200
}
}
}Submit a generic IOC to the AI engine and return the latest available v14 result plus queue status.
If the IOC has not been scored yet, this endpoint enqueues it for analysis and returns a queue status. Use ai_status_ioc to poll processing state and ai_search_ioc for strict read-only lookup.
Required Permission: ai:score
| token | string |
| method required | string Value: "ai_score_ioc" |
| ioc required | string HTTP(S) URL, domain name or IP address |
{- "token": "your_api_key",
- "method": "ai_score_ioc",
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}Retrieve the latest stored v14 AI result for an already scored IOC.
This endpoint is strictly read-only. It does not enqueue new analysis. If the IOC is not already materialized in the AI database, the response is 404 IocNotFound. Use ai_score_ioc to enqueue or score a new URL, domain or IP.
Required Permission: ai:search
| token | string |
| method required | string Value: "ai_search_ioc" |
| ioc required | string HTTP(S) URL, domain name or IP address |
{- "token": "string",
- "method": "ai_search_ioc",
- "ioc": "string"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}Return the current queue state and latest result if one is already materialized.
Required Permission: ai:search
| token | string |
| method required | string Value: "ai_status_ioc" |
| ioc required | string HTTP(S) URL, domain name or IP address |
{- "token": "string",
- "method": "ai_status_ioc",
- "ioc": "string"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}Return a summarized v14 profile, queue status and public-safe evidence fields without raw private payloads.
Required Permission: ai:search
| token | string |
| method required | string Value: "ai_profile_ioc" |
| ioc required | string HTTP(S) URL, domain name or IP address |
{- "token": "string",
- "method": "ai_profile_ioc",
- "ioc": "string"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}Search up to 500 URL/domain/IP IOCs in one private request. This endpoint does not enqueue new scans.
Required Permission: ai:search
| token | string |
| method required | string Value: "ai_search_bulk" |
| iocs required | Array of strings [ 1 .. 500 ] items |
{- "token": "string",
- "method": "ai_search_bulk",
- "iocs": [
- "string"
]
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}Queue up to 100 URL/domain/IP IOCs in one private request and return the latest available result for each.
Required Permission: ai:score
| token | string |
| method required | string Value: "ai_score_bulk" |
| priority | boolean Default: true |
| iocs required | Array of strings [ 1 .. 100 ] items |
{- "token": "string",
- "method": "ai_score_bulk",
- "priority": true,
- "iocs": [
- "string"
]
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}Export materialized AI rows updated after a date. Supports cursor pagination and optional verdict, IOC type, category and score filters.
Required Permission: ai:list
| token | string |
| method required | string Value: "ai_export_delta" |
| updated_after required | string <date-time> |
| cursor | integer Default: 0 |
| per_page | integer <= 1000 Default: 250 |
| verdict | string Enum: "safe" "suspicious" "malicious" |
| ioc_type | string Enum: "url" "domain" "ip" |
| category | string |
| min_score | number [ 0 .. 1 ] |
{- "token": "string",
- "method": "ai_export_delta",
- "updated_after": "2019-08-24T14:15:22Z",
- "cursor": 0,
- "per_page": 250,
- "verdict": "safe",
- "ioc_type": "url",
- "category": "string",
- "min_score": 1
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": { }
}List scored AI entries with cursor-based pagination.
Only fully scored entries are returned. SQL row identifiers are not exposed in entry objects; use next_cursor only as an opaque pagination value for the next request.
Required Permission: ai:list
| token | string Your API key |
| method required | string Value: "ai_list_entries" |
| cursor | integer >= 0 Default: 0 Opaque pagination cursor returned by the previous response. Use 0 for the first page. |
| per_page | integer [ 1 .. 500 ] Default: 100 Number of entries to return |
{- "token": "your_api_key",
- "method": "ai_list_entries",
- "cursor": 0,
- "per_page": 100
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "entries": [
- {
- "ioc": "example.com",
- "verdict": "safe",
- "score": 0.12,
- "timestamp_created": 1776530000,
- "timestamp_updated": 1776530200,
- "scanned": "yes",
- "priority": "high",
- "mode": "primary",
- "risk_band": "safe",
- "risk_score": 0.12,
- "risk_score_10": 1.2,
- "ml_label": "safe",
- "ml_score": 0.08,
- "primary_category": "Legitimate",
- "primary_category_group": "General",
- "primary_category_confidence": 0.96,
- "primary_taxonomy_version": "crdf-security-category-v14",
- "secondary_category_safe": "Unrated/Unknown",
- "secondary_category_safe_family": "Background/Unknown",
- "secondary_category_safe_confidence": 0.82,
- "secondary_category_safe_source": "safe_abstain",
- "secondary_category_decision": "General/Other",
- "secondary_category_decision_family": "Background/Unknown",
- "secondary_category_decision_confidence": 0.74,
- "secondary_category_decision_source": "fallback_non_security",
- "secondary_category_decision_legacy": "Unrated",
- "secondary_category_taxonomy_version": "crdf-secondary-openworld-v14",
- "secondary_category_evidence": [ ],
- "secondary_category_safe_evidence": [ ],
- "secondary_openworld_scored_at": 1776530200,
- "top_related_score": 0,
- "factor_count": 5,
- "model_version": "domain.v14.model@local",
- "schema_version": "crdf-v14-domain-1",
- "service_mode": "primary",
- "captured_at": 1776530200
}
], - "next_cursor": 31639439
}
}Submit a false-positive request for a blacklisted URL.
This endpoint is public (no permission required).
Optional Permission: false_positive:auto_accept - If present and force_deleted is set to true, the request is automatically accepted and the URL is removed immediately (bypasses expert review).
| token | string Your API key |
| method required | string Value: "false_positive_ng" |
| url required | string <uri> URL of the site to mark as false positive |
| force_deleted | boolean If true and permitted, request is auto-accepted and URL is removed immediately |
{- "token": "your_api_key",
- "method": "false_positive_ng",
- "force_deleted": true
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "msg": "The false positive has been received and is being processed.",
- "force_deleted": "no",
- "domain_name": "example.com",
- "ref": "202506011234567890",
}
}Retrieve information on a false-positive request by reference.
This endpoint is public (no permission required). A reference is only visible to the API key that created the request.
| token | string Your API key |
| method required | string Value: "false_positive_getinfos" |
| ref required | string Reference of your false positive request |
{- "token": "your_api_key",
- "method": "false_positive_getinfos",
- "ref": "20230409474197"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "url": [
- {
- "ID": 36451803,
- "domainName": "perdus.com",
- "category": "Suspect:URL",
- "timeAdded": 1680372908,
- "isBlacklisted": 0,
- "isAdvert": 0,
- "permanent": 0
}
], - "request": [
- {
- "ID_URL": 36451803,
- "domain_name": "perdus.com",
- "reference": "20230401810821",
- "timestamp": 1680372228,
- "timestamp_end": null,
- "status": "new",
- "step": "finished",
- "verdict": "deleted",
- "force_deleted": "no"
}
],
}
}Returns all WHOIS-related data (domain, registrar, DNS-SEC, name servers, statuses) in JSON format for the specified domain name.
Required Permission: whois
| token | string Your API key |
| method required | string Value: "whois_get" |
| domain_name required | string^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?... Valid domain name (e.g., crdf.fr, example.com) |
{- "token": "your_api_key",
- "method": "whois_get",
- "domain_name": "crdf.fr"
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "domain": {
- "ID_DOMAIN": 2006834,
- "ID_DNS_SEC": 2,
- "ID_REGISTRAR": 1283,
- "domain_name": "crdf.fr",
- "domain_tld": "whois.afnic.fr",
- "query_time": 1737196730,
- "create_date": "2006-10-18 15:03:41",
- "update_date": "2024-09-26 10:10:55",
- "expiry_date": "2027-10-18 15:03:41"
}, - "registrar": {
- "ID_REGISTRAR": 1283,
- "name": "NETIM",
- "iana": null,
- "whoisserver": "whois.afnic.fr",
- "phone": null,
- "timestamp": 1726916260,
- "hash": "6bfdc3578007fd7feb1a46763adda54d8d385875"
}, - "dns_sec": {
- "ID_DNS_SEC": 2,
- "status": "false"
}, - "name_servers": [
- {
- "ID_DOMAIN_R_NS": 4783526,
- "ID_NAME_SERVER": 824,
- "ID_DOMAIN": 2006834,
- "name": "bob.ns.cloudflare.com"
}, - {
- "ID_DOMAIN_R_NS": 4783527,
- "ID_NAME_SERVER": 840,
- "ID_DOMAIN": 2006834,
- "name": "erin.ns.cloudflare.com"
}
], - "status": [
- {
- "ID_DOMAIN_R_STATUS": 3330951,
- "ID_STATUS": 4,
- "ID_DOMAIN": 2006834,
- "status": "ACTIVE",
- "description": "Common WHOIS status values: ACTIVE, clientDeleteProhibited, clientTransferProhibited,\nclientUpdateProhibited, serverDeleteProhibited, serverTransferProhibited, serverUpdateProhibited\n"
}
]
}
}Returns a paginated list of WHOIS domains (ID_DOMAIN, domain_name, domain_tld, query_time, create_date, update_date, expiry_date). Pagination is cursor-based.
Required Permission: whois
| token | string Your API key |
| method required | string Value: "whois_list_domains" |
| cursor | integer Default: 0 Last-seen ID_DOMAIN (exclusive). Use 0 to start at the first record. |
| per_page | integer [ 1 .. 500 ] Default: 100 Number of records to return (max 500) |
{- "token": "your_api_key",
- "method": "whois_list_domains",
- "cursor": 1000,
- "per_page": 50
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "domains": [
- {
- "ID_DOMAIN": 1001,
- "domain_name": "example.com",
- "domain_tld": "whois.verisign-grs.com",
- "query_time": 1745000000,
- "create_date": "2025-06-01 10:00:00",
- "update_date": "2025-06-05 12:00:00",
- "expiry_date": "2026-06-01 10:00:00"
}, - {
- "ID_DOMAIN": 1002,
- "domain_name": "mysite.org",
- "domain_tld": "whois.pir.org",
- "query_time": 1745000050,
- "create_date": "2025-06-02 09:30:00",
- "update_date": "2025-06-04 11:15:00",
- "expiry_date": "2026-06-02 09:30:00"
}
], - "next_cursor": 1002
}
}Retrieve a list of newly registered domains (NRDs) stored in the database, using cursor-based pagination.
Required Permission: nrd
| token | string Your API key |
| method required | string Value: "get_nrd" |
| cursor | integer >= 0 Default: 0 Last-seen NRD ID (exclusive). Use 0 to start from the first record. Pagination: See pagination documentation in |
| per_page | integer [ 1 .. 500 ] Default: 100 Number of records to return per page (max 500) |
{- "token": "your_api_key",
- "method": "get_nrd",
- "cursor": 150,
- "per_page": 50
}{- "error": false,
- "error_code": null,
- "message": null,
- "data": {
- "nrd": [
- {
- "ID": 151,
- "domain": "example151.com",
- "timestamp_created": 1744870057
}, - {
- "ID": 152,
- "domain": "example152.com",
- "timestamp_created": 1744870060
}
], - "next_cursor": 200
}
}Returns the current malicious IOC decisions published by CRDF AI as a native STIX 2.1 Bundle. Safe, indeterminate and insufficient-evidence decisions are excluded. Internal models, thresholds, source details and private evidence are never exported.
Required permissions: licensed private account and cti:ai
Pagination is returned through the X-CRDF-Next and Link response
headers. Pass the opaque value back as the next query parameter.
| added_after | string <date-time> Return objects added strictly after this RFC 3339 UTC timestamp. |
| limit | integer [ 1 .. 500 ] Default: 100 |
| next | string Opaque cursor returned by the previous page. It is bound to the API key and filters. |
{- "type": "bundle",
- "id": "string",
- "objects": [
- {
- "type": "indicator",
- "spec_version": "2.1",
- "id": "string",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "name": "string",
- "indicator_types": [
- "string"
], - "pattern": "string",
- "pattern_type": "stix",
- "pattern_version": "2.1",
- "valid_from": "2019-08-24T14:15:22Z",
- "confidence": 100,
- "object_marking_refs": [
- "string"
]
}
]
}Returns active malicious URL and domain telemetry as a native STIX 2.1 Bundle. URL user-info, fragments and query strings are removed before publication to prevent accidental disclosure of secrets or personal data.
Required permissions: licensed private account and cti:url-telemetry
Pagination is returned through the X-CRDF-Next and Link response
headers. Pass the opaque value back as the next query parameter.
| added_after | string <date-time> Return objects added strictly after this RFC 3339 UTC timestamp. |
| limit | integer [ 1 .. 500 ] Default: 100 |
| next | string Opaque cursor returned by the previous page. It is bound to the API key and filters. |
{- "type": "bundle",
- "id": "string",
- "objects": [
- {
- "type": "indicator",
- "spec_version": "2.1",
- "id": "string",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "name": "string",
- "indicator_types": [
- "string"
], - "pattern": "string",
- "pattern_type": "stix",
- "pattern_version": "2.1",
- "valid_from": "2019-08-24T14:15:22Z",
- "confidence": 100,
- "object_marking_refs": [
- "string"
]
}
]
}Returns the TAXII 2.1 discovery document. This resource is reserved for
licensed private accounts and requires private plus taxii:read.
{- "title": "string",
- "description": "string",
}Requires a licensed private account and taxii:read. Returns only
collections authorized for the supplied API key.
{- "collections": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "can_read": true,
- "can_write": true,
- "media_types": [
- "string"
]
}
]
}| collection_id required | string <uuid> |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "can_read": true,
- "can_write": true,
- "media_types": [
- "string"
]
}| collection_id required | string <uuid> |
| added_after | string <date-time> Return objects added strictly after this RFC 3339 UTC timestamp. |
| limit | integer [ 1 .. 500 ] Default: 100 |
| next | string Opaque cursor returned by the previous page. It is bound to the API key and filters. |
| match[id] | string |
| match[type] | string Value: "indicator" |
| match[version] | string <date-time> |
| match[spec_version] | string Value: "2.1" |
{- "more": true,
- "next": "string",
- "objects": [
- {
- "type": "indicator",
- "spec_version": "2.1",
- "id": "string",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "name": "string",
- "indicator_types": [
- "string"
], - "pattern": "string",
- "pattern_type": "stix",
- "pattern_version": "2.1",
- "valid_from": "2019-08-24T14:15:22Z",
- "confidence": 100,
- "object_marking_refs": [
- "string"
]
}
]
}| collection_id required | string <uuid> |
| added_after | string <date-time> Return objects added strictly after this RFC 3339 UTC timestamp. |
| limit | integer [ 1 .. 500 ] Default: 100 |
| next | string Opaque cursor returned by the previous page. It is bound to the API key and filters. |
| match[id] | string |
| match[type] | string Value: "indicator" |
| match[version] | string <date-time> |
| match[spec_version] | string Value: "2.1" |
{- "more": true,
- "next": "string",
- "objects": [
- {
- "id": "string",
- "date_added": "2019-08-24T14:15:22Z",
- "version": "2019-08-24T14:15:22Z",
- "media_type": "string"
}
]
}| collection_id required | string <uuid> |
| object_id required | string^indicator--[a-f0-9-]{36}$ |
{- "more": true,
- "next": "string",
- "objects": [
- {
- "type": "indicator",
- "spec_version": "2.1",
- "id": "string",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "name": "string",
- "indicator_types": [
- "string"
], - "pattern": "string",
- "pattern_type": "stix",
- "pattern_version": "2.1",
- "valid_from": "2019-08-24T14:15:22Z",
- "confidence": 100,
- "object_marking_refs": [
- "string"
]
}
]
}