REST API Reference
This document describes the official AlphaSOC REST API. The primary purpose of the API is to allow a wide variety of clients for sending network telemetry and receiving alerts. API endpoints are complementary to other data sources and alert escalations in a way that alerts generated for network telemetry submitted outside of the API are available to download via API and vice versa.
Schema
The API can be accessed at https://api.alphasoc.net over HTTPS. All requests and responses
are encoded in JSON.
Compression
As the amount of data transmitted via API can be high, it's advisable to use the compression both ways.
Usually HTTP clients transparently support compression when fetching data (by providing Accept-Encoding header),
but the upload needs to be handled manually. AlphaSOC API supports gzip and deflate compression algorithms
and it's recommended to compress large chunks of data (telemetry) before sending, along with attaching corresponding
Content-Encoding header.
Rate limiting
API counts and limits number of requests per workspace, shared by all its API keys. The limits are not strictly defined and designed
to protect from flooding and accidental errors in client's implementation. In the unlikely case of hitting the limit
API returns 429 Too Many Requests response and expects the client to retry after some time.
Authentication
All the API requests should be authenticated using Basic Authentication where API key is provided as a username and leaving the password empty.
You can generate API keys in the console.
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | - |
| 400 | Bad Request | Bad request | errorMessage |
| 401 | Unauthorized | Bad request | errorMessage |
| 403 | Forbidden | Forbidden | errorMessage |
| 429 | Too Many Requests | Too many requests | errorMessage |
Account management
GET /v1/account/status
This call can be used to fetch general information about the account, e.g. registration status, key expiration time, and current license usage. Human-readable messages from the system are also included in the response, so they can be presented in the UI.
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | accountStatus |
Example 200 response
{
"today": "2018-08-28T10:33:37.137110423Z",
"registered": false,
"expired": false,
"expirationDate": "2018-09-27T10:31:32.196658Z",
"endpointsSeenToday": 2338,
"messages": [
{
"level": 2,
"body": "Your API key is not activated. Alerts are suppressed until you have activated your account."
}
]
}
Code samples
curl -X GET -u "<your-api-key>:" https://api.alphasoc.net/v1/account/status \
-H 'Accept: application/json'
Detection management
POST /v1/detections
Handles the upload of Sigma detection rules via a zip archive.
The import_mode query parameter controls how rules are processed: merge adds new rules and updates existing ones, while replace removes all existing customer-provided Sigma rules before adding the new ones.
The zip archive must contain Sigma rule files with .yaml or .yml extensions.
The following limits apply:
- Maximum number of files in archive: 5000
- Maximum size of a single rule file: 1MB
- Maximum total decompressed size of all rules: 50MB
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| import_mode | query | string | false | Specifies the import mode. merge adds new rules and updates existing ones. replace replaces all existing customer-provided Sigma rules. |
| dry_run | query | boolean | false | Specifies if the request will be run in dry run mode. If true, the request will be validated, but no changes will be persisted. |
| body | body | binary | true | A zip archive containing Sigma rule files (.yaml or .yml). |
Enumerated Values
| Parameter | Value |
|---|---|
| import_mode | merge (default) |
| import_mode | replace |
| dry_run | false (default) |
| dry_run | true |
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Sigma rules processed successfully | detectionsUpload |
| 400 | Bad Request | The request was malformed or contained invalid detection files. The response body will contain details about the errors | detectionsBadRequest |
| 401 | Unauthorized | Unauthorized | errorMessage |
| 403 | Forbidden | Forbidden | errorMessage |
| 415 | Unsupported Media Type | Unsupported media type | errorMessage |
| 429 | Too Many Requests | Too many requests | errorMessage |
Example 200 response
{
"accepted": 10
}
Example 400 response
{
"message": "One or more detection files failed.",
"validationResult": {
"valid": 5,
"invalid": 2,
"errors": [
{
"fileName": "malformed_rule.yml",
"error": "invalid Sigma rule: missing required field 'detection'"
}
]
}
}
Code samples
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/detections \
-H 'Content-Type: application/zip' \
-H 'Accept: application/json' \
--data-binary @./path/to/rules.zip
Retrieving Findings
GET /v1/findings
This endpoint allows for fetching findings generated from logs submitted to the AlphaSOC Analytics Engine (via API or other sources). Each finding includes detections along with the associated resources and context. It might also include sampled log entries that triggered the detection.
Threat details can be accessed via additional threats dictionary, but note that for a given
threat ID the description and severity can be amended at any time – in such the case the changes are valid for all the
historical findings already retrieved. The full and most recent threat dictionary is also available using (inventory endpoints)[#inventory].
The API uses stream pagination to limit the size of individual responses and allow reading stream of data in continuous manner. Each response includes a follow bookmark, which should be passed as a parameter in subsequent requests to retrieve only new results. When the last page is reached, the more property in the response is set to false.
Usually the flow for retrieving findings looks like this:
- Fetch new findings via
/v1/findings?schema=ocsf&follow={lastFollowBookmark}. - If
response.More == truethen go back to [1] immediately. - If
response.More == falsethen sleep for some time and go back to [1].
It is also possible to use ndjson format for findings. In such case, the stream pagination values are returned in x-stream-more and x-stream-follow headers.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| follow | query | string | false | Bookmark provided by one of the previous responses. Only new findings since the bookmark will be returned. |
| schema | query | string | false | Returned schema of the findings. Currently only ocsf value is supported. |
| maxAge | query | string | false | Specifies maximum age of alerts to return. |
| Accept | header | string | false | Specifies the format of the response. Defaults to application/json. |
Detailed descriptions
schema: Returned schema of the findings. Currently only ocsf value is supported.
maxAge: Specifies maximum age of alerts to return. Value can be represented in seconds (s), minutes (m), hours (h) or days (d) up to 30d. Defaults to 3 days.
Accept: Specifies the format of the response. Defaults to application/json.
Enumerated Values
| Parameter | Value |
|---|---|
| schema | ocsf |
| Accept | application/json |
| Accept | application/x-ndjson |
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | findings |
Example 200 response
{
"follow": "string",
"more": true,
"records": [
{
"category_name": "Findings",
"category_uid": 2,
"class_name": "DetectionFinding",
"class_uid": 2004,
"type_name": "DetectionFinding: Create",
"type_uid": 200401,
"count": 4,
"time": 1725679437,
"time_dt": "2024-09-07T03:23:57Z",
"enrichments": [
{
"data": {
"aggregation": {
"key": {
"workspaceID": "9269f7ee-115c-46da-8445-62ebff28217e",
"srcIP": "192.168.40.17",
"detections": [
{
"id": "c2",
"key": "LokiBot",
"severity": 5,
"observations": [],
"mitreAttack": [],
"threat": "c2_communication"
}
]
},
"keyHash": "29f4fedb9f3f0316",
"batchIDs": [
"9269f7ee-115c-46da-8445-62ebff28217e/615fb9dd883ed28d3351dcaf7bfefdb91cddd7fc"
]
}
},
"name": "finding_info",
"type": "alphasoc",
"value": ""
}
],
"metadata": {
"processed_time": 1725679437,
"processed_time_dt": "2024-09-07T03:23:57Z",
"product": {
"vendor_name": "AlphaSOC"
},
"profiles": [
"datetime"
],
"version": "1.2.0"
},
"observables": [
{
"name": "device.ip",
"type": "IP Address",
"type_id": 2,
"value": "192.168.40.17"
},
{
"name": "evidences[].query.hostname",
"type": "Hostname",
"type_id": 1,
"value": "coffeinoffice.xyz"
},
{
"name": "evidences[].src_endpoint.ip",
"type": "IP Address",
"type_id": 2,
"value": "192.168.40.17"
},
{
"name": "evidences[].src_endpoint.port",
"type": "Port",
"type_id": 11,
"value": "62963"
}
],
"severity": "Critical",
"severity_id": 5,
"activity_id": 1,
"activity_name": "Create",
"device": {
"ip": "192.168.40.17",
"type_id": 0
},
"end_time": 1725678925,
"end_time_dt": "2024-09-07T03:15:25Z",
"finding_info": {
"attacks": [
{
"tactic": {
"uid": "TA0011"
},
"technique": {
"uid": "T1071"
}
}
],
"created_time": 1725679437,
"created_time_dt": "2024-09-07T03:23:57Z",
"desc": "C2 communication attempt indicating infection",
"title": "AlphaSOC aggregated finding",
"types": [
"c2"
],
"uid": "d0924ebd-c44c-4645-83b5-4cc8649fabdb"
},
"start_time": 1725678544,
"start_time_dt": "2024-09-07T03:09:04Z",
"evidences": [
{
"data": {
"event": {
"type": "dns",
"ts": "2024-09-07T03:09:04.135822919Z",
"srcIP": "192.168.40.17",
"srcPort": 62963,
"body": {
"fqdn": "coffeinoffice.xyz",
"qtype": "A",
"rcode": ""
}
},
"wisdom": {
"flags": [
"bad_tld",
"c2"
],
"labels": [
"c2:LokiBot"
],
"domain": "coffeinoffice.xyz"
}
},
"query": {
"type": "A",
"hostname": "coffeinoffice.xyz"
},
"src_endpoint": {
"ip": "192.168.40.17",
"port": 62963
}
}
]
}
]
}
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Stream-Follow | string | Follow bookmark to be used in subsequent requests | |
| 200 | X-Stream-More | boolean | Indicator whether there are more findings to retrieve |
Code samples
curl -X GET -u "<your-api-key>:" https://api.alphasoc.net/v1/findings \
-H 'Accept: application/json' \
-H 'Accept: application/x-ndjson'
Searching the Data Lake
The data lake holds the telemetry AlphaSOC processes and the indicators AlphaSOC extracts from
it for threat analysis, in OCSF v1.5.0 form. You search it
with POST /v1/lake/query.
Commands
Each query starts with a command that picks what you search:
| Command | Returns | Searchable history | Filter |
|---|---|---|---|
event | Ingested telemetry, one OCSF event per record. | 30 days | Optional |
evidence | Indicators AlphaSOC extracted: queried domains, contacted IP addresses and URLs, TLS certificates, API callers, and executed files. | 180 days | At least one selector or filter term |
activity | The evidence indicators, joined with the device and user AlphaSOC saw them on. | 180 days | At least one selector or filter term |
stats | Event volume per credential, data origin, and data type, by hour or over longer intervals. See Event volume statistics. | 7 days by default, 31 days per request at most | Data origin selectors and intervalHours only |
Query syntax
A query has this form:
<command> [selectors and filter terms]
Selectors and filter terms can appear in any order. Commands, AND, and OR work in any case.
The filter combines field=value terms on OCSF field paths:
- Terms with no operator between them combine with
AND:device.ip=10.0.0.5 dst_endpoint.port=443equalsdevice.ip=10.0.0.5 AND dst_endpoint.port=443. ANDbinds tighter thanOR, soa OR b AND cmeansa OR (b AND c). Use parentheses to group terms differently.- An unquoted value can contain ASCII letters, digits, and
. * _ : / -. Put any other value in single or double quotes, for exampleactor.user.name="alice@example.com"oractor.user.name="John Doe". In the JSON request body, escape double quotes as\":"query": "event actor.user.name=\"John Doe\"". - You can quote a field path too, for example
"process.file.hashes[].value"=<hash>. Quote the path and the value on their own, and keep the=outside the quotes.
Selectors limit which part of the lake the search scans. To match several values of a selector,
join them with OR in parentheses:
(class_name=dns_activity OR class_name=network_activity) device.ip=10.0.0.5. OR can only
join values of the same selector: the server rejects a selector joined by OR to a filter term,
such as class_name=dns_activity OR device.ip=10.0.0.5.
| Selector | Commands | Values |
|---|---|---|
class_name | event | An OCSF class name from Event classes, in snake_case, Title Case, or dash-separated form, such as dns_activity, "DNS Activity", or dns-activity. |
metadata.product.name | event, activity, stats | A data origin name, such as aws-cloudtrail or zeek-dns. The name must match in full, including case. |
dataOrigin | stats | Same as metadata.product.name. |
evidence_type | evidence, activity | dns, ip, http, tls, audit, or system. |
Searchable fields
Device and user fields work with event and activity:
| Field | Description | Example |
|---|---|---|
device.ip | Device IP address | 10.0.0.0/24 |
device.hostname | Device hostname | workstation-01 |
device.uid | Device identifier, such as a CrowdStrike AID | 09e8771fc488477d9cddb61b5fd32c6c |
device.mac | Device MAC address | 00:1A:2B:3C:4D:5E |
actor.user.name | User name | alice |
metadata.tenant_uid | Data scope the record belongs to | aws:123456789012:us-east-1: |
Indicator fields work with event, evidence, and activity:
| Field | Description | Example |
|---|---|---|
query.hostname | Queried domain name (DNS records only) | *.example.org |
query.type | DNS query type | A |
src_endpoint.ip | Caller IP address of API, authentication, and account change records | 192.0.2.10 |
dst_endpoint.ip | Destination IP address | 198.51.100.7 |
dst_endpoint.port | Destination port | 443 |
connection_info.protocol_name | IP protocol | tcp |
http_request.http_method | HTTP request method | GET |
http_request.url.hostname | Hostname of the requested URL (HTTP records only) | *.example.org |
http_request.url.path | Path of the requested URL | /beacon |
http_request.url.scheme | Scheme of the requested URL | https |
http_request.url.url_string | Full requested URL | https://example.org/beacon |
http_request.user_agent | HTTP client user agent | curl/8.5.0 |
tls.certificate.fingerprints[0].value | TLS server certificate fingerprint | 0db6495611891de35650a18ad91002845f9cc6bc |
tls.certificate.subject | TLS server certificate subject | "CN=example.org" |
tls.certificate.issuer | TLS server certificate issuer | "CN=GTS CA,O=Google Trust Services,C=US" |
tls.ja3_hash.value | JA3 TLS client fingerprint | 0b2a5b08a7c44adaeaa1c0d29493c409 |
tls.ja3s_hash.value | JA3S TLS server fingerprint | 254c31292ed05b84addc077fe6cee283 |
process.file.name | Process file name | powershell.exe |
process.file.hashes[].value | Process file hash, MD5 or SHA-256 | d41d8cd98f00b204e9800998ecf8427e |
In activity, device and user fields combine with indicator fields through AND only. The
server rejects an OR across the two groups, such as
device.ip=10.0.0.5 OR query.hostname=example.org.
Value rules:
- IP address fields take an IPv4 address or a
/16,/24, or/32CIDR range. The server rejects other prefix lengths, IPv6 addresses, and0.0.0.0. query.hostnameandhttp_request.url.hostnametake a domain or a leading wildcard such as*.example.org.dst_endpoint.porttakes1to65535. For HTTP records it matches the URL's effective port: the port in the URL, or the scheme default, sohttps://example.org/matches443.http_request.url.pathmatches the path alone. The server rejects a value containing?or#, because the lake doesn't index query strings or fragments.http_request.url.url_stringtakes a full URL and matches its scheme, host, effective port, and path. It ignores the query string and fragment.http://example.orgmatches every path on that host, whilehttp://example.org/matches the root path alone.- Hash and fingerprint fields take hex values. The server ignores colons and spaces in them.
device.mactakes a MAC address. It matches the separators the data source used, so copy the value from a returned record.- Other fields take a plain string.
- Field values ignore case, so
query.type=aaaamatchesAAAA.
Event classes
The event command maps each record to an OCSF class:
| OCSF class | UID |
|---|---|
| Base Event | 0 |
| DNS Activity | 4003 |
| Network Activity | 4001 |
| HTTP Activity | 4002 |
| API Activity | 6003 |
| Process Activity | 1007 |
| Authentication | 3002 |
| Account Change | 3001 |
| File System Activity | 1001 |
| Kernel Extension Activity | 1002 |
| Module Activity | 1005 |
| Scheduled Job Activity | 1006 |
| Script Activity | 1009 |
event returns events without a class-specific mapping as Base Event, with the original event
under raw_data. Select them with class_name=base_event. SentinelOne Deep Visibility records
of the file, module, driver, login, cross-process, command script, and scheduled task
categories match filters on device.uid and device.hostname alone.
Event volume statistics
Use stats to check how many events AlphaSOC processed, and which credentials, data origins,
and data types sent them.
- With no selector,
statscovers every data origin. - An unknown origin name returns
400.dataOrigin=unknownselects events recorded with theunknownorigin. Events that arrived with no origin appear only in a query with no selector. - Any field besides the origin selectors and
intervalHoursreturns400, and so do two origins joined withAND. - AlphaSOC stores statistics in whole-hour buckets, so
statswidens the range to every hour it touches: 10:20 to 11:10 returns the full 10:00 and 11:00 buckets. The current hour may be incomplete. - The response size limit doesn't apply to
stats.
Each record covers one hour by default. To summarize longer intervals, such as days, add
intervalHours=<hours>: stats intervalHours=24 (dataOrigin=aws-cloudtrail OR dataOrigin=zeek-dns).
- Intervals start at the beginning of the range, rounded down to the hour. When the range isn't a
multiple of
intervalHours, the last interval is shorter, and itsintervalHoursshows how many hours it covers. A 7-day range ending at 10:20 covers 169 hours, sointervalHours=24returns seven 24-hour intervals and a final 1-hour interval. intervalHours=0returns one interval covering the whole range.- The value must be a whole number of hours, no longer than the range. Giving
intervalHourstwice returns400.
Each record covers one credential, interval, data origin, and data type. stats sorts records
by interval, then credential, data origin, and data type.
| Field | Description |
|---|---|
data.time | Start of the interval, in Unix epoch milliseconds |
data.timeBucket | Start of the interval, as an RFC 3339 UTC timestamp |
data.intervalHours | Number of hours the interval covers |
data.credentialID | Credential that sent the events; the zero UUID when the events had no credential |
data.dataOrigin | Data origin as recorded; an empty string means the events carried no origin |
data.dataType | Data type, such as dns or audit |
data.stats.events | Exact number of events processed |
data.stats.dataScopes | Approximate number of distinct data scopes |
data.stats.endpoints | Approximate number of distinct endpoints |
One data scope or endpoint can appear in several records, so adding dataScopes or endpoints
across records overcounts. To count them over a longer period, use intervalHours: each record
counts them once across its whole interval.
POST /v1/lake/query
Searches the data lake and streams matching records as newline-delimited JSON
(application/x-ndjson), one JSON object per line.
For the query syntax, see Searching the Data Lake.
Time range
since and until take RFC 3339 timestamps, and until defaults to now. event, evidence,
and activity need since. The server shortens a range that starts before their searchable
history, and returns 400 when no part of the range falls inside it.
If you run the same event, evidence, or activity query again within an hour, the server
can return a cached response that leaves out data added since the first run.
Response format
Each line of the response is one of:
{"data": {...}}: a matching record.eventreturns an OCSF event.evidenceandactivityreturn an OCSF Base Event with the indicators in itsevidences[]array.statsreturns a statistics row.{"error": "..."}: a record the server couldn't return, or a failure that ended the search.{"limitReached": true, "limitReason": "..."}: a response limit cut the search short. It comes last, as its own line or as two fields on the lastdataorerrorline.
If the search fails before the first line, the server returns 500 with an empty body.
Records from event, evidence, and activity arrive in no particular order. limitReason
names the limit that cut the search short:
limitReason | Meaning |
|---|---|
bytes | The matching records reached about 10 MB. |
rows | The search hit the most lake data one query can scan. |
partial | The server couldn't read part of the matching data. A retry usually returns the full result. |
A search stops after 90 seconds. To get a full result, narrow the filter or the time range. A
range shorter than 5 minutes doesn't avoid the bytes and rows limits, and a bytes response
can be smaller than 10 MB.
Data lake queries have a tighter rate limit than other endpoints. When you split a search into several requests, space them out.
Examples
The server sends each record on one line; the examples spread it over several for reading. Replace the dates with a range inside the command's searchable history.
DNS queries from a subnet for subdomains of example.org:
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/lake/query \
-H 'Content-Type: application/json' \
-d '{"since": "2026-10-12T00:00:00Z", "until": "2026-10-13T00:00:00Z", "query": "event class_name=dns_activity device.ip=10.20.30.0/24 query.hostname=*.example.org"}'
{
"data": {
"activity_id": 1,
"activity_name": "Query",
"actor": { "user": { "name": "jdoe" } },
"category_name": "Network Activity",
"category_uid": 4,
"class_name": "DNS Activity",
"class_uid": 4003,
"device": { "hostname": "workstation-7", "ip": "10.20.30.40", "uid": "device-7" },
"metadata": {
"product": { "name": "zeek-dns" },
"profiles": ["datetime", "host"],
"tenant_uid": "corp",
"version": "1.5.0"
},
"query": { "hostname": "malicious.example.org", "type": "A" },
"rcode": "NoError",
"rcode_id": 0,
"severity": "Informational",
"severity_id": 1,
"time": 1791806400000,
"time_dt": "2026-10-12T12:00:00.000Z",
"type_name": "DNS Activity: Query",
"type_uid": 400301
}
}
AWS CloudTrail API calls from one caller IP address:
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/lake/query \
-H 'Content-Type: application/json' \
-d '{"since": "2026-10-12T00:00:00Z", "until": "2026-10-13T00:00:00Z", "query": "event class_name=api_activity metadata.product.name=aws-cloudtrail src_endpoint.ip=203.0.113.9"}'
{
"data": {
"activity_id": 2,
"activity_name": "Read",
"actor": {
"session": { "is_mfa": true },
"user": { "name": "jdoe", "type": "IAMUser", "uid": "arn:aws:iam::123456789012:user/jdoe" }
},
"api": { "operation": "GetObject", "service": { "name": "s3.amazonaws.com" } },
"category_name": "Application Activity",
"category_uid": 6,
"class_name": "API Activity",
"class_uid": 6003,
"cloud": { "account": { "uid": "123456789012" }, "provider": "AWS", "region": "us-east-1" },
"http_request": { "user_agent": "aws-cli/2.15.0" },
"metadata": {
"event_code": "AwsApiCall",
"product": { "name": "aws-cloudtrail" },
"profiles": ["datetime"],
"tenant_uid": "aws:123456789012:us-east-1:",
"uid": "11111111-2222-3333-4444-555555555555",
"version": "1.5.0"
},
"severity": "Informational",
"severity_id": 1,
"src_endpoint": { "ip": "203.0.113.9" },
"time": 1791806400000,
"time_dt": "2026-10-12T12:00:00.000Z",
"type_name": "API Activity: Read",
"type_uid": 600302
}
}
HTTP evidence for a URL path on a host:
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/lake/query \
-H 'Content-Type: application/json' \
-d '{"since": "2026-10-06T00:00:00Z", "until": "2026-10-13T00:00:00Z", "query": "evidence evidence_type=http http_request.url.hostname=malicious.example.org http_request.url.path=/beacon"}'
{
"data": {
"activity_id": 99,
"activity_name": "AlphaSOC Evidence",
"category_uid": 0,
"class_uid": 0,
"metadata": {
"product": { "name": "alphasoc-wisdom" },
"profiles": ["datetime"],
"uid": "<opaque record ID>",
"version": "1.5.0"
},
"severity_id": 0,
"time": 1791806400000,
"time_dt": "2026-10-12T12:00:00.000Z",
"type_uid": 0,
"evidences": [
{
"dst_endpoint": { "port": 443 },
"http_request": {
"url": {
"hostname": "malicious.example.org",
"path": "/beacon",
"scheme": "https",
"url_string": "https://malicious.example.org/beacon"
},
"user_agent": "curl/8.5.0"
},
"uid": "<opaque evidence ID>"
}
]
}
}
Devices and users in a subnet that resolved a domain:
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/lake/query \
-H 'Content-Type: application/json' \
-d '{"since": "2026-10-06T00:00:00Z", "until": "2026-10-13T00:00:00Z", "query": "activity device.ip=10.20.30.0/24 query.hostname=malicious.example.org"}'
{
"data": {
"activity_id": 99,
"activity_name": "AlphaSOC Activity",
"category_uid": 0,
"class_uid": 0,
"metadata": {
"product": { "name": "zeek-dns" },
"profiles": ["datetime"],
"tenant_uid": "corp",
"uid": "<opaque record ID>",
"version": "1.5.0"
},
"severity_id": 0,
"time": 1791806400000,
"time_dt": "2026-10-12T12:00:00.000Z",
"type_uid": 0,
"evidences": [
{
"actor": { "user": { "name": "jdoe" } },
"device": { "hostname": "workstation-7", "ip": "10.20.30.40", "type_id": 0, "uid": "device-7" },
"query": { "hostname": "malicious.example.org", "type": "A" },
"uid": "<opaque evidence ID>"
}
]
}
}
With no device or user filter and no metadata.product.name selector, activity also returns
indicators with no observed source. Those records carry no device or actor, and their
metadata.product.name is alphasoc-wisdom. You can't use that value as a selector.
Hourly event volume for two data origins:
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/lake/query \
-H 'Content-Type: application/json' \
-d '{"since": "2026-10-05T10:20:00Z", "until": "2026-10-12T11:10:00Z", "query": "stats (dataOrigin=aws-cloudtrail OR dataOrigin=zeek-dns)"}'
{
"data": {
"time": 1791194400000,
"credentialID": "11111111-1111-4111-8111-111111111111",
"timeBucket": "2026-10-05T10:00:00Z",
"intervalHours": 1,
"dataOrigin": "aws-cloudtrail",
"dataType": "audit",
"stats": { "events": 4200, "dataScopes": 3, "endpoints": 12 }
}
}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | lakeQuery | true | At most 10,000 bytes. |
Body parameter
{
"since": "2026-10-12T00:00:00Z",
"until": "2026-10-13T00:00:00Z",
"query": "event actor.user.name=\"John Doe\""
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | lakeRecord |
Example 200 response
{
"data": {
"actor": {
"user": {
"name": "John Doe"
}
},
"class_name": "DNS Activity",
"class_uid": 4003,
"device": {
"ip": "10.20.30.40"
},
"query": {
"hostname": "malicious.example.org",
"type": "A"
},
"time": 1791806400000
}
}
Code samples
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/lake/query \
-H 'Content-Type: application/json' \
-H 'Accept: application/x-ndjson' \
-d '{"since":"2026-10-12T00:00:00Z","until":"2026-10-13T00:00:00Z","query":"event actor.user.name=\"John Doe\""}'
Retrieving Alerts
GET /v1/alerts
Deprecated: it is recomended to use /v1/findings instead.
This endpoint allows for fetching alerts generated by network telemetry submitted to the AlphaSOC Analytics Engine (via API or other sources). Each alert includes the original (although normalized) event along with the associated threats and context.
Threat details can be accessed via additional threats dictionary included in the response, but note that for a given
threat ID the description and severity can be amended at any time – in such the case the changes are valid for all the
historical alerts already retrieved. The full and most recent threat dictionary is also available using inventory endpoints.
The API uses pagination to limit the size of individual responses. Each response includes a follow bookmark, which should be passed as a parameter in subsequent requests to retrieve only new results. When the last page is reached, the more property in the response is set to false.
Usually the flow for retrieving alerts looks like this:
- Fetch new alerts via
/v1/alerts?follow={lastFollowBookmark}. - If
response.More == truethen go back to [1] immediately. - If
response.More == falsethen sleep for some time and go back to [1].
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| follow | query | string | false | Page bookmark as provided by one of the previous responses. Only new alerts since the bookmark will be returned. |
| maxAge | query | string | false | Specifies maximum age of alerts to return. |
Detailed descriptions
maxAge: Specifies maximum age of alerts to return. Value can be represented in seconds (s), minutes (m) or hours (h) up to 720h (30 days).
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | alerts |
Example 200 response
{
"follow": "string",
"more": true,
"alerts": [
{
"eventType": "string",
"threats": [
"c2_communication"
],
"wisdom": {
"flags": [
"c2",
"young_domain"
],
"labels": [
"c2:TrickBot"
],
"domain": "example.com"
},
"event": {
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"query": "www.example.com",
"qtype": "A"
}
}
],
"threats": {
"c2_communication": {
"title": "C2 communication attempt indicating infection",
"severity": 5
},
"cryptomining": {
"title": "Cryptomining indicating infection or resource abuse",
"severity": 4
}
}
}
Code samples
curl -X GET -u "<your-api-key>:" --compressed https://api.alphasoc.net/v1/alerts \
-H 'Accept: application/json'
Sending Telemetry
Network telemetry can be submitted for scoring using multiple endpoints – each one for specific type of events (DNS, IP, etc.). Events are submitted in batches containing a stream of JSON objects with every object representing an individual network event. For example:
{dnsEvent1}{dnsEvent2}{dnsEvent3}...
There is no limit for number of events one can send, but there is a limit of uncompressed body size (currently 10MB). It is advisable to compress the data before uploading, see Compression for details.
POST /v1/events/dns
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Content-Encoding | header | string | false | Sets compression |
| body | body | dnsEvent | false | none |
Body parameter
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"query": "www.example.com",
"qtype": "A"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | eventsResponseBody |
Example 200 response
{
"received": 100,
"accepted": 100
}
Code samples
# Without compression
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/events/dns \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","query":"www.example.com","qtype":"A"}'
# With compression
curl -u "<your-api-key>:" https://api.alphasoc.net/v1/events/dns \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @<(echo '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","query":"www.example.com","qtype":"A"}' | gzip)
POST /v1/events/ip
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Content-Encoding | header | string | false | Sets compression |
| body | body | ipEvent | false | none |
Body parameter
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"destIP": "8.8.8.8",
"destPort": 23,
"proto": "udp",
"bytesIn": 3911,
"bytesOut": 2512,
"packetsIn": 11,
"packetsOut": 7,
"app": "ssl",
"action": "allowed",
"duration": 7.2
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | eventsResponseBody |
Example 200 response
{
"received": 100,
"accepted": 100
}
Code samples
# Without compression
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/events/ip \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","destIP":"8.8.8.8","destPort":23,"proto":"udp","bytesIn":3911,"bytesOut":2512,"packetsIn":11,"packetsOut":7,"app":"ssl","action":"allowed","duration":7.2}'
# With compression
curl -u "<your-api-key>:" https://api.alphasoc.net/v1/events/ip \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @<(echo '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","destIP":"8.8.8.8","destPort":23,"proto":"udp","bytesIn":3911,"bytesOut":2512,"packetsIn":11,"packetsOut":7,"app":"ssl","action":"allowed","duration":7.2}' | gzip)
POST /v1/events/tls
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Content-Encoding | header | string | false | Sets compression |
| body | body | tlsEvent | false | none |
Body parameter
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"certHash": "9fcc5c1e8ec32f56e975ba43c923dbfa16a8f946",
"issuer": "C=US; O=DigiCert Inc; OU=www.digicert.com; CN=GeoTrust RSA CA 2018",
"subject": "C=US,ST=TX,L=Texas,O=lol,OU=,CN=example.com",
"validFrom": "2021-03-30T00:34:02Z",
"validTo": "2021-05-29T00:34:02Z",
"destIP": "188.68.55.50",
"destPort": 9001,
"ja3": "724dedf93fb5a3636a0f1ee8fcec8801",
"ja3s": "015535be754766257f9bfdf3470cd428e0f1cfd4"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | eventsResponseBody |
Example 200 response
{
"received": 100,
"accepted": 100
}
Code samples
# Without compression
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/events/tls \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","certHash":"9fcc5c1e8ec32f56e975ba43c923dbfa16a8f946","issuer":"C=US; O=DigiCert Inc; OU=www.digicert.com; CN=GeoTrust RSA CA 2018","subject":"C=US,ST=TX,L=Texas,O=lol,OU=,CN=example.com","validFrom":"2021-03-30T00:34:02Z","validTo":"2021-05-29T00:34:02Z","destIP":"188.68.55.50","destPort":9001,"ja3":"724dedf93fb5a3636a0f1ee8fcec8801","ja3s":"015535be754766257f9bfdf3470cd428e0f1cfd4"}'
# With compression
curl -u "<your-api-key>:" https://api.alphasoc.net/v1/events/tls \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @<(echo '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","certHash":"9fcc5c1e8ec32f56e975ba43c923dbfa16a8f946","issuer":"C=US; O=DigiCert Inc; OU=www.digicert.com; CN=GeoTrust RSA CA 2018","subject":"C=US,ST=TX,L=Texas,O=lol,OU=,CN=example.com","validFrom":"2021-03-30T00:34:02Z","validTo":"2021-05-29T00:34:02Z","destIP":"188.68.55.50","destPort":9001,"ja3":"724dedf93fb5a3636a0f1ee8fcec8801","ja3s":"015535be754766257f9bfdf3470cd428e0f1cfd4"}' | gzip)
POST /v1/events/http
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Content-Encoding | header | string | false | Sets compression |
| body | body | httpEvent | false | none |
Body parameter
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"url": "http://microsoft775.com/wpad.dat",
"method": "GET",
"status": 200,
"app": "http",
"action": "allowed",
"bytesIn": 4321,
"bytesOut": 1234,
"contentType": "text/html; charset=utf-8",
"referrer": "someone.com",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | eventsResponseBody |
Example 200 response
{
"received": 100,
"accepted": 100
}
Code samples
# Without compression
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/events/http \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","url":"http://microsoft775.com/wpad.dat","method":"GET","status":200,"app":"http","action":"allowed","bytesIn":4321,"bytesOut":1234,"contentType":"text/html; charset=utf-8","referrer":"someone.com","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"}'
# With compression
curl -u "<your-api-key>:" https://api.alphasoc.net/v1/events/http \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @<(echo '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","url":"http://microsoft775.com/wpad.dat","method":"GET","status":200,"app":"http","action":"allowed","bytesIn":4321,"bytesOut":1234,"contentType":"text/html; charset=utf-8","referrer":"someone.com","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"}' | gzip)
POST /v1/events/lease
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Content-Encoding | header | string | false | Sets compression |
| body | body | leaseEvent | false | none |
Body parameter
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"type": "string",
"termination": true,
"duration": 5.4
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | eventsResponseBody |
Example 200 response
{
"received": 100,
"accepted": 100
}
Code samples
# Without compression
curl -X POST -u "<your-api-key>:" https://api.alphasoc.net/v1/events/lease \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","type":"string","termination":true,"duration":5.4}'
# With compression
curl -u "<your-api-key>:" https://api.alphasoc.net/v1/events/lease \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @<(echo '{"ts":"2018-03-01T10:31:59Z","srcIP":"192.168.20.5","srcPort":32876,"srcHost":"john-pc","srcMac":"16:c8:60:26:09:a6","srcUser":"john","srcID":"string","type":"string","termination":true,"duration":5.4}' | gzip)
Inventory
GET /v1/ae/inventory/threats
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | aeThreats |
Example 200 response
{
"threats": {
"c2_communication": {
"title": "C2 communication attempt indicating infection",
"severity": 5
},
"cryptomining": {
"title": "Cryptomining indicating infection or resource abuse",
"severity": 4
}
}
}
Code samples
curl -X GET -u "<your-api-key>:" https://api.alphasoc.net/v1/ae/inventory/threats \
-H 'Accept: application/json'
GET /v1/ae/inventory/flags
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | aeFlags |
Example 200 response
{
"flags": {
"c2": {
"title": "Known C2 callback destination",
"type": "category"
},
"freedns": {
"title": "Parent domain is a dynamic DNS provider",
"type": "feature"
}
}
}
Code samples
curl -X GET -u "<your-api-key>:" https://api.alphasoc.net/v1/ae/inventory/flags \
-H 'Accept: application/json'
Schemas
accountStatus
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| today | string(date-time) | false | Today's date |
| registered | boolean | false | Registration status |
| expired | boolean | false | Key expiration status |
| expirationDate | string(date-time) | false | Key expiration date |
| endpointsSeenToday | integer | false | Key usage status |
| messages | [message] | false | Human readable messages from the system |
Example
{
"today": "2018-08-28T10:33:37.137110423Z",
"registered": false,
"expired": false,
"expirationDate": "2018-09-27T10:31:32.196658Z",
"endpointsSeenToday": 2338,
"messages": [
{
"level": 2,
"body": "Your API key is not activated. Alerts are suppressed until you have activated your account."
}
]
}
message
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| level | integer | false | Message level |
| body | string | false | Message text |
Enumerated Values
| Property | Value | Description |
|---|---|---|
| level | 1 | 1 - INFO |
| level | 2 | 2 - WARN |
| level | 3 | 3 - ERROR |
Example
{
"level": 2,
"body": "Your API key is not activated. Alerts are suppressed until you have activated your account."
}
alerts
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| follow | string | false | Page bookmark. Can be passed to consecutive request to retrieve only new alerts since the last query. |
| more | boolean | false | Indicates if there are more alerts to retrieve. |
| alerts | [alert] | false | Array of alerts. |
| threats | threats | false | Dictionary containing definition of threats. |
Example
{
"follow": "string",
"more": true,
"alerts": [
{
"eventType": "string",
"threats": [
"c2_communication"
],
"wisdom": {
"flags": [
"c2",
"young_domain"
],
"labels": [
"c2:TrickBot"
],
"domain": "example.com"
},
"event": {
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"query": "www.example.com",
"qtype": "A"
}
}
],
"threats": {
"c2_communication": {
"title": "C2 communication attempt indicating infection",
"severity": 5
},
"cryptomining": {
"title": "Cryptomining indicating infection or resource abuse",
"severity": 4
}
}
}
alert
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| eventType | string | false | EventType describes type of event object ("dns", "ip", "http", "tls"). |
| threats | [string] | false | Threats associated with alert. |
| wisdom | wisdom | false | Wisdom context of alert. |
| event | any | false | One of the *Event schema described in the table below. |
oneOf
| Name | Type | Required | Description |
|---|---|---|---|
| - | dnsEvent | false | DNS query event |
| - | ipEvent | false | IP traffic event |
| - | httpEvent | false | HTTP request event |
| - | tlsEvent | false | TLS event |
Example
{
"eventType": "string",
"threats": [
"c2_communication"
],
"wisdom": {
"flags": [
"c2",
"young_domain"
],
"labels": [
"c2:TrickBot"
],
"domain": "example.com"
},
"event": {
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"query": "www.example.com",
"qtype": "A"
}
}
findings
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| follow | string | false | Page bookmark. Can be passed to consecutive request to retrieve only new findings since the last query. |
| more | boolean | false | Indicates if there are more findings to retrieve. |
| records | [finding] | false | [OCSF v1.2.0 Detection Finding. For more information about the schema see OCSF specification.] |
Example
{
"follow": "string",
"more": true,
"records": [
{
"category_name": "Findings",
"category_uid": 2,
"class_name": "DetectionFinding",
"class_uid": 2004,
"type_name": "DetectionFinding: Create",
"type_uid": 200401,
"count": 4,
"time": 1725679437,
"time_dt": "2024-09-07T03:23:57Z",
"enrichments": [
{
"data": {
"aggregation": {
"key": {
"workspaceID": "9269f7ee-115c-46da-8445-62ebff28217e",
"srcIP": "192.168.40.17",
"detections": [
{
"id": "c2",
"key": "LokiBot",
"severity": 5,
"observations": [],
"mitreAttack": [],
"threat": "c2_communication"
}
]
},
"keyHash": "29f4fedb9f3f0316",
"batchIDs": [
"9269f7ee-115c-46da-8445-62ebff28217e/615fb9dd883ed28d3351dcaf7bfefdb91cddd7fc"
]
}
},
"name": "finding_info",
"type": "alphasoc",
"value": ""
}
],
"metadata": {
"processed_time": 1725679437,
"processed_time_dt": "2024-09-07T03:23:57Z",
"product": {
"vendor_name": "AlphaSOC"
},
"profiles": [
"datetime"
],
"version": "1.2.0"
},
"observables": [
{
"name": "device.ip",
"type": "IP Address",
"type_id": 2,
"value": "192.168.40.17"
},
{
"name": "evidences[].query.hostname",
"type": "Hostname",
"type_id": 1,
"value": "coffeinoffice.xyz"
},
{
"name": "evidences[].src_endpoint.ip",
"type": "IP Address",
"type_id": 2,
"value": "192.168.40.17"
},
{
"name": "evidences[].src_endpoint.port",
"type": "Port",
"type_id": 11,
"value": "62963"
}
],
"severity": "Critical",
"severity_id": 5,
"activity_id": 1,
"activity_name": "Create",
"device": {
"ip": "192.168.40.17",
"type_id": 0
},
"end_time": 1725678925,
"end_time_dt": "2024-09-07T03:15:25Z",
"finding_info": {
"attacks": [
{
"tactic": {
"uid": "TA0011"
},
"technique": {
"uid": "T1071"
}
}
],
"created_time": 1725679437,
"created_time_dt": "2024-09-07T03:23:57Z",
"desc": "C2 communication attempt indicating infection",
"title": "AlphaSOC aggregated finding",
"types": [
"c2"
],
"uid": "d0924ebd-c44c-4645-83b5-4cc8649fabdb"
},
"start_time": 1725678544,
"start_time_dt": "2024-09-07T03:09:04Z",
"evidences": [
{
"data": {
"event": {
"type": "dns",
"ts": "2024-09-07T03:09:04.135822919Z",
"srcIP": "192.168.40.17",
"srcPort": 62963,
"body": {
"fqdn": "coffeinoffice.xyz",
"qtype": "A",
"rcode": ""
}
},
"wisdom": {
"flags": [
"bad_tld",
"c2"
],
"labels": [
"c2:LokiBot"
],
"domain": "coffeinoffice.xyz"
}
},
"query": {
"type": "A",
"hostname": "coffeinoffice.xyz"
},
"src_endpoint": {
"ip": "192.168.40.17",
"port": 62963
}
}
]
}
]
}
finding
OCSF v1.2.0 Detection Finding. For more information about the schema see OCSF specification.
Example
{
"category_name": "Findings",
"category_uid": 2,
"class_name": "DetectionFinding",
"class_uid": 2004,
"type_name": "DetectionFinding: Create",
"type_uid": 200401,
"count": 4,
"time": 1725679437,
"time_dt": "2024-09-07T03:23:57Z",
"enrichments": [
{
"data": {
"aggregation": {
"key": {
"workspaceID": "9269f7ee-115c-46da-8445-62ebff28217e",
"srcIP": "192.168.40.17",
"detections": [
{
"id": "c2",
"key": "LokiBot",
"severity": 5,
"observations": [
"bad"
],
"mitreAttack": [
"TA0011:T1071"
],
"threat": "c2_communication"
}
]
},
"keyHash": "29f4fedb9f3f0316",
"batchIDs": [
"9269f7ee-115c-46da-8445-62ebff28217e/615fb9dd883ed28d3351dcaf7bfefdb91cddd7fc"
]
}
},
"name": "finding_info",
"type": "alphasoc",
"value": ""
}
],
"metadata": {
"processed_time": 1725679437,
"processed_time_dt": "2024-09-07T03:23:57Z",
"product": {
"vendor_name": "AlphaSOC"
},
"profiles": [
"datetime"
],
"version": "1.2.0"
},
"observables": [
{
"name": "device.ip",
"type": "IP Address",
"type_id": 2,
"value": "192.168.40.17"
},
{
"name": "evidences[].query.hostname",
"type": "Hostname",
"type_id": 1,
"value": "coffeinoffice.xyz"
},
{
"name": "evidences[].src_endpoint.ip",
"type": "IP Address",
"type_id": 2,
"value": "192.168.40.17"
},
{
"name": "evidences[].src_endpoint.port",
"type": "Port",
"type_id": 11,
"value": "62963"
}
],
"severity": "Critical",
"severity_id": 5,
"activity_id": 1,
"activity_name": "Create",
"device": {
"ip": "192.168.40.17",
"type_id": 0
},
"end_time": 1725678925,
"end_time_dt": "2024-09-07T03:15:25Z",
"finding_info": {
"attacks": [
{
"tactic": {
"uid": "TA0011"
},
"technique": {
"uid": "T1071"
}
}
],
"created_time": 1725679437,
"created_time_dt": "2024-09-07T03:23:57Z",
"desc": "C2 communication attempt indicating infection",
"title": "AlphaSOC aggregated finding",
"types": [
"c2"
],
"uid": "d0924ebd-c44c-4645-83b5-4cc8649fabdb"
},
"start_time": 1725678544,
"start_time_dt": "2024-09-07T03:09:04Z",
"evidences": [
{
"data": {
"event": {
"type": "dns",
"ts": "2024-09-07T03:09:04.135822919Z",
"srcIP": "192.168.40.17",
"srcPort": 62963,
"body": {
"fqdn": "coffeinoffice.xyz",
"qtype": "A",
"rcode": ""
}
},
"wisdom": {
"flags": [
"bad_tld",
"c2"
],
"labels": [
"c2:LokiBot"
],
"domain": "coffeinoffice.xyz"
}
},
"query": {
"type": "A",
"hostname": "coffeinoffice.xyz"
},
"src_endpoint": {
"ip": "192.168.40.17",
"port": 62963
}
}
]
}
lakeQuery
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| since | string(date-time) | false | Start of the time range, as an RFC 3339 timestamp. event, evidence, and activity need it. |
| until | string(date-time) | false | End of the time range, as an RFC 3339 timestamp. Defaults to now. |
| query | string | true | Command, selectors, and filter expression. See Searching the Data Lake. |
Example
{
"since": "2026-10-12T00:00:00Z",
"until": "2026-10-13T00:00:00Z",
"query": "event actor.user.name=\"John Doe\""
}
lakeRecord
One line of the NDJSON response.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| data | object | false | The matching record. |
| error | string | false | Error message. |
| limitReached | boolean | false | Appears on the last line, alone or with data or error, when a response limit cut the search short. |
| limitReason | string | false | The limit that cut the search short. |
Enumerated Values
| Property | Value |
|---|---|
| limitReason | bytes |
| limitReason | rows |
| limitReason | partial |
Example
{
"data": {
"actor": {
"user": {
"name": "John Doe"
}
},
"class_name": "DNS Activity",
"class_uid": 4003,
"device": {
"ip": "10.20.30.40"
},
"query": {
"hostname": "malicious.example.org",
"type": "A"
},
"time": 1791806400000
}
}
detectionsUpload
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| accepted | integer | false | Number of Sigma rules that were successfully processed and accepted. |
Example
{
"accepted": 10
}
detectionsBadRequest
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| message | string | false | Message text |
| validationResult | object | false | Detailed validation results when validation errors occur |
| valid | integer | false | Number of detections that passed validation and were stored |
| invalid | integer | false | Number of detections that failed validation or storage |
| errors | [object] | false | Detailed validation errors for each invalid rule |
| »fileName | string | false | Name of the Sigma rule file that caused the error |
| »error | string | false | Error message describing the issue |
Example
{
"message": "One or more detection files failed.",
"validationResult": {
"valid": 5,
"invalid": 2,
"errors": [
{
"fileName": "malformed_rule.yml",
"error": "invalid Sigma rule: missing required field 'detection'"
}
]
}
}
wisdom
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| flags | [string] | false | none |
| labels | [string] | false | none |
| domain | string | false | none |
Example
{
"flags": [
"c2",
"young_domain"
],
"labels": [
"c2:TrickBot"
],
"domain": "example.com"
}
eventHeader
Common properties for each type of event
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| ts | string(date-time) | false | Event timestamp |
| srcIP | string(ip) | false | Source IP |
| srcPort | integer | false | Source port |
| srcHost | string | false | Source host |
| srcMac | string | false | Source MAC address |
| srcUser | string | false | Source user |
| srcID | string | false | Source ID |
Example
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string"
}
dnsEvent
DNS query event
allOf
| Name | Type | Required | Description |
|---|---|---|---|
| - | eventHeader | false | Common properties for each type of event |
and
| Name | Type | Required | Description |
|---|---|---|---|
| - | object | false | none |
| query | string | false | DNS query |
| qtype | string | false | Query type |
Example
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"query": "www.example.com",
"qtype": "A"
}
ipEvent
IP traffic event
allOf
| Name | Type | Required | Description |
|---|---|---|---|
| - | eventHeader | false | Common properties for each type of event |
and
| Name | Type | Required | Description |
|---|---|---|---|
| - | object | false | none |
| destIP | string(ip) | false | Destination IP |
| destPort | integer | false | Destination port |
| proto | string | false | Transport layer protocol |
| bytesIn | integer(int64) | false | Number of incoming bytes |
| bytesOut | integer(int64) | false | Number of outgoing bytes |
| packetsIn | integer(int64) | false | Number of incoming packets |
| packetsOut | integer(int64) | false | Number of outgoing packets |
| app | string | false | Application layer protocol |
| action | string | false | Defines if event was allowed or denied |
| duration | number(double) | false | Duration of connection |
Example
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"destIP": "8.8.8.8",
"destPort": 23,
"proto": "udp",
"bytesIn": 3911,
"bytesOut": 2512,
"packetsIn": 11,
"packetsOut": 7,
"app": "ssl",
"action": "allowed",
"duration": 7.2
}
httpEvent
HTTP request event
allOf
| Name | Type | Required | Description |
|---|---|---|---|
| - | eventHeader | false | Common properties for each type of event |
and
| Name | Type | Required | Description |
|---|---|---|---|
| - | object | false | none |
| url | string | false | HTTP request URL |
| method | string | false | HTTP method |
| status | integer(int64) | false | HTTP response status code |
| app | string | false | Application layer protocol |
| action | string | false | Defines if event was allowed or denied |
| bytesIn | integer(int64) | false | Number of incoming bytes |
| bytesOut | integer(int64) | false | Number of outgoing bytes |
| contentType | string | false | Content type of HTTP event |
| referrer | string | false | none |
| userAgent | string | false | User Agent used in HTTP event |
Example
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"url": "http://microsoft775.com/wpad.dat",
"method": "GET",
"status": 200,
"app": "http",
"action": "allowed",
"bytesIn": 4321,
"bytesOut": 1234,
"contentType": "text/html; charset=utf-8",
"referrer": "someone.com",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
}
tlsEvent
TLS event
allOf
| Name | Type | Required | Description |
|---|---|---|---|
| - | eventHeader | false | Common properties for each type of event |
and
| Name | Type | Required | Description |
|---|---|---|---|
| - | object | false | none |
| certHash | string | false | Certificate hash |
| issuer | string | false | Certificate issuer |
| subject | string | false | Certificate subject |
| validFrom | string(date-time) | false | From when certificate is valid |
| validTo | string(date-time) | false | Certificate expiration date |
| destIP | string(ip) | false | Destination IP |
| destPort | integer | false | Destination port |
| ja3 | string | false | JA3 fingerprint |
| ja3s | string | false | JA3S fingerprint |
Example
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"certHash": "9fcc5c1e8ec32f56e975ba43c923dbfa16a8f946",
"issuer": "C=US; O=DigiCert Inc; OU=www.digicert.com; CN=GeoTrust RSA CA 2018",
"subject": "C=US,ST=TX,L=Texas,O=lol,OU=,CN=example.com",
"validFrom": "2021-03-30T00:34:02Z",
"validTo": "2021-05-29T00:34:02Z",
"destIP": "188.68.55.50",
"destPort": 9001,
"ja3": "724dedf93fb5a3636a0f1ee8fcec8801",
"ja3s": "015535be754766257f9bfdf3470cd428e0f1cfd4"
}
leaseEvent
DHCP query event
allOf
| Name | Type | Required | Description |
|---|---|---|---|
| - | eventHeader | false | Common properties for each type of event |
and
| Name | Type | Required | Description |
|---|---|---|---|
| - | object | false | none |
| type | string | false | none |
| termination | boolean | false | none |
| duration | integer(int64) | false | Duration of the event |
Example
{
"ts": "2018-03-01T10:31:59Z",
"srcIP": "192.168.20.5",
"srcPort": 32876,
"srcHost": "john-pc",
"srcMac": "16:c8:60:26:09:a6",
"srcUser": "john",
"srcID": "string",
"type": "string",
"termination": true,
"duration": 5.4
}
aeThreats
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| threats | threats | false | Dictionary containing definition of threats. |
Example
{
"threats": {
"c2_communication": {
"title": "C2 communication attempt indicating infection",
"severity": 5
},
"cryptomining": {
"title": "Cryptomining indicating infection or resource abuse",
"severity": 4
}
}
}
threats
Dictionary containing definition of threats.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| threatID | threat | false | none |
Example
{
"c2_communication": {
"title": "C2 communication attempt indicating infection",
"severity": 5
},
"cryptomining": {
"title": "Cryptomining indicating infection or resource abuse",
"severity": 4
}
}
threat
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| title | string | true | Human readable description of the threat |
| severity | integer | true | Severity of the threat |
| policy | boolean | false | none |
Example
{
"title": "human readable description",
"severity": 5,
"policy": true
}