On this page

Device intelligence API

Read devices, events and visits, export data, fetch the sealed-results key, write labels, and manage behavioral baselines.

Server-to-server reads and writes over the devices, events and visits your integrations collected. Authenticate with an sk_ server API key whose scopes cover the operation: read:device, read:fingerprints, read:events, read:visits, read:export, read:sealed_results, write:labels, write:generate, read:behavioral and erase:behavioral. Base URL: https://collect.noxtica.com.

The signed verdict webhooks (submission.scored, risk.high, risk.flagged, risk.cluster_flagged, account.agent_linked) are documented in this area too.

EnvironmentBase URL
Productionhttps://collect.noxtica.com

Credential: ApiKeyAuth. See Authentication.

How this page is organisedBar length shows each section’s share of the text. Select a section to jump to it.

Devices

3 operations

Events & Visits

2 operations

Exports

5 operations

Sealed Results

1 operation

Labels

2 operations

Generator

2 operations

Behavioral Baseline

3 operations

Operations in Device intelligence API

Look up a device by ID

GET /v1/device/{deviceId}

Returns the current score and risk projection of one device — the fingerprintId your browser or mobile integration received — scoped to the calling organisation.

The route answers 404 with {"error":"Device not found","deviceId":"...","requestId":"..."} when the device is unknown, belongs to another organisation, or has not been seen within your organisation’s configured retention window.

  • reasonCodes is the published, non-personal reason-code projection of the internal flags. It is an empty array unless reason-code output is enabled for your organisation, independently of the raw flags field.
  • gpuAttestationTier is masked: a stored hardware or software tier is reported as attested unless publication of the hardware attestation level is enabled for your organisation. gpuVerified is not masked and never asserts hardware.
  • subscores and details are the scorer’s per-domain breakdown when present, otherwise null. softwareSubfp, hardwareSubfp and environmentSubfp are server-derived observational sub-fingerprints; they are null for devices recorded before those fields existed.

Authentication: Bearer token (ApiKeyAuth), scope read:device.

Parameters

NameInTypeRequiredDescription
deviceIdpathstringYesThe device_id to look up (URL-decoded from the path segment).

Responses

StatusMeaningError codesContent
200The device’s current score/risk projection.application/json
400Missing/empty deviceId, or the path segment failed URL-decoding.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
404{ error: 'Device not found', deviceId, requestId } — tenant projection inactive/missing OR the row is absent/outside the retention window.Device not foundapplication/json
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
deviceobjectYes
device.deviceIdstringNo
device.domainIdstringNo
device.scorenumberNo
device.riskLevelstringNo
device.confidencenumber, nullableNo
device.flagsarray of stringNo
device.reasonCodesarray of stringNoEmpty unless reason-code output is enabled for your organisation.
device.subscoresobject, nullableNo
device.detailsobject, nullableNo
device.countrystring, nullableNo
device.citystring, nullableNo
device.createdAtstring (date-time)No
device.updatedAtstring (date-time)No
device.lastSubmittedAtstring (date-time), nullableNo
device.lastSeenAtstring (date-time), nullableNo
device.gpuVerifiedbooleanNo
device.gpuAttestationTierstring, nullableNoMasked unless publication of the hardware attestation level is enabled for your organisation; see description above. Allowed values: attested, suspicious, unavailable, failed, hardware, software.
device.softwareSubfpstring, nullableNo
device.hardwareSubfpstring, nullableNo
device.environmentSubfpstring, nullableNo

Response example (200)

{
  "ok": true,
  "device": {
    "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
    "domainId": "dom_3f2a8c91d6e5f470",
    "score": 1,
    "riskLevel": "low",
    "confidence": 1,
    "flags": [
      "example-flags"
    ],
    "reasonCodes": [
      "example-reasonCodes"
    ],
    "subscores": {},
    "details": {},
    "country": "US",
    "city": "Istanbul",
    "createdAt": "2026-09-13T12:00:00.000Z",
    "updatedAt": "2026-09-13T12:00:00.000Z",
    "lastSubmittedAt": "2026-09-13T12:00:00.000Z",
    "lastSeenAt": "2026-09-13T12:00:00.000Z",
    "gpuVerified": true,
    "gpuAttestationTier": "attested",
    "softwareSubfp": "example-softwareSubfp",
    "hardwareSubfp": "example-hardwareSubfp",
    "environmentSubfp": "example-environmentSubfp"
  }
}

Example request

curl

curl "https://collect.noxtica.com/v1/device/example-deviceId" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/device/example-deviceId', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/device/example-deviceId",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

List devices

GET /v1/devices

Lists devices, most recently updated first, with filters and keyset pagination. from and to bound the range and may span at most 400 days. source selects real devices, synthetic devices (see the generator operations) or both; all merges both result sets by (updated_at, device_id) descending.

cursor is opaque: pass the nextCursor of the previous page back unchanged and never construct one. limit defaults to 50 and is capped at 200.

Authentication: Bearer token (ApiKeyAuth), scope read:fingerprints.

Parameters

NameInTypeRequiredDescription
limitqueryintegerNoMinimum 1, maximum 200. Default 50.
cursorquerystringNoOpaque keyset cursor from a prior response’s nextCursor.
fromquerystring (date-time)NoDefaults to 400 days before now.
toquerystring (date-time)NoDefaults to now.
domain_idquerystringNo
risk_levelquerystringNoFilter by risk level; the allowed set is deps-injected (riskLevelFilterValues).
sourcequerystringNoAllowed values: real, synthetic, all. Default real.

Responses

StatusMeaningError codesContent
200A page of devices.application/json
400Invalid source, Invalid risk_level, or Invalid date range (bad/inverted/over-400-day from/to).invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500{ error: 'Failed to query devices', code: 'devices_list_query_failed' } on a warehouse fault, or a generic internal error.invalid_requestapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
devicesarray of objectYes
devices[]objectNo
devices[].deviceIdstringNo
devices[].domainIdstringNo
devices[].scorenumber, nullableNo
devices[].riskLevelstring, nullableNo
devices[].flagsarray of stringNo
devices[].countrystring, nullableNo
devices[].createdAtstring (date-time)No
devices[].updatedAtstring (date-time)No
devices[].isSyntheticbooleanNo
hasMorebooleanYes
nextCursorstring, nullableYes

Response example (200)

{
  "ok": true,
  "devices": [
    {
      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domainId": "dom_3f2a8c91d6e5f470",
      "score": 1,
      "riskLevel": "low",
      "flags": [
        "example-flags"
      ],
      "country": "US",
      "createdAt": "2026-09-13T12:00:00.000Z",
      "updatedAt": "2026-09-13T12:00:00.000Z",
      "isSynthetic": true
    }
  ],
  "hasMore": true,
  "nextCursor": "cursor_000123"
}

Example request

curl

curl "https://collect.noxtica.com/v1/devices" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/devices', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/devices",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

List devices linked to an account

GET /v1/accounts/{accountHash}/devices

Lists the devices and agents linked to one of your end-user accounts, with their current score and risk only. accountHash must be the keyed 16-character lowercase-hex pseudonym your organisation already receives elsewhere (for example the account_hash filter of GET /v1/events); a raw account id is never accepted on this path.

Pagination is a keyset cursor over (last_seen_at, id) descending, with the same opaque cursor shape as GET /v1/events.

Authentication: Bearer token (ApiKeyAuth), scope read:fingerprints.

Parameters

NameInTypeRequiredDescription
accountHashpathstringYesThe keyed 16-hex-lowercase account pseudonym. Pattern ^[0-9a-f]{16}$.
limitqueryintegerNoMinimum 1, maximum 200. Default 50.
cursorquerystringNo

Responses

StatusMeaningError codesContent
200The account’s linked device/agent history.application/json
400accountHash fails the 16-hex-lowercase shape check.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500{ error: 'Failed to query account devices', code: 'account_devices_query_failed' } or a generic internal error.invalid_requestapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
accountHashstringYes
linksarray of objectYes
links[]objectNo
links[].agentKeyidstringNo
links[].agentHoststring, nullableNo
links[].deviceIdstringNo
links[].domainIdstringNo
links[].firstSeenAtintegerNoEpoch ms.
links[].lastSeenAtintegerNoEpoch ms.
links[].seenCountintegerNo
links[].deviceScorenumber, nullableNo
links[].deviceRiskLevelstring, nullableNo
links[].deviceUpdatedAtstring, nullableNo
hasMorebooleanYes
nextCursorstring, nullableYes

Response example (200)

{
  "ok": true,
  "accountHash": "a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f89",
  "links": [
    {
      "agentKeyid": "example-agentKeyid",
      "agentHost": "example-agentHost",
      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domainId": "dom_3f2a8c91d6e5f470",
      "firstSeenAt": 1,
      "lastSeenAt": 1,
      "seenCount": 1,
      "deviceScore": 1,
      "deviceRiskLevel": "example-deviceRiskLevel",
      "deviceUpdatedAt": "example-deviceUpdatedAt"
    }
  ],
  "hasMore": true,
  "nextCursor": "cursor_000123"
}

Example request

curl

curl "https://collect.noxtica.com/v1/accounts/example-accountHash/devices" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/accounts/example-accountHash/devices', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/accounts/example-accountHash/devices",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

List scoring events

GET /v1/events

Lists scored events, newest first, with a keyset cursor over (created_at, id). The optional account_hash filter (a keyed 16-character lowercase-hex pseudonym) applies to source=real only: synthetic events and the merged all view carry no account_hash.

reasonCodes is the published reason-code projection of the event’s internal flags; it is empty unless reason-code output is enabled for your organisation.

Authentication: Bearer token (ApiKeyAuth), scope read:events.

Parameters

NameInTypeRequiredDescription
device_idquerystringNo
fromquerystring (date-time)No
toquerystring (date-time)No
domain_idquerystringNo
account_hashquerystringNoApplied only when source resolves to real. Pattern ^[0-9a-f]{16}$.
sourcequerystringNoAllowed values: real, synthetic, all. Default real.
limitqueryintegerNoMinimum 1, maximum 200. Default 50.
cursorquerystringNo

Responses

StatusMeaningError codesContent
200A page of events.application/json
400Invalid source, or account_hash fails the 16-hex-lowercase shape check.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
eventsarray of objectYes
events[]objectNo
events[].idstringNo
events[].deviceIdstringNo
events[].domainIdstringNo
events[].scorenumber, nullableNo
events[].riskLevelstring, nullableNo
events[].confidencenumber, nullableNo
events[].flagsarray of stringNo
events[].reasonCodesarray of stringNo
events[].countrystring, nullableNo
events[].createdAtstring (date-time)No
events[].payloadUnavailableboolean, nullableNo
events[].isSyntheticbooleanNo
hasMorebooleanYes
nextCursorstring, nullableYes

Response example (200)

{
  "ok": true,
  "events": [
    {
      "id": "example-id",
      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domainId": "dom_3f2a8c91d6e5f470",
      "score": 1,
      "riskLevel": "low",
      "confidence": 1,
      "flags": [
        "example-flags"
      ],
      "reasonCodes": [
        "example-reasonCodes"
      ],
      "country": "US",
      "createdAt": "2026-09-13T12:00:00.000Z",
      "payloadUnavailable": true,
      "isSynthetic": true
    }
  ],
  "hasMore": true,
  "nextCursor": "cursor_000123"
}

Example request

curl

curl "https://collect.noxtica.com/v1/events" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/events', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/events",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

List visits

GET /v1/visits

Lists visit records, newest first, with a keyset cursor over (created_at, id). Visits have no synthetic partition, so this route has no source filter. meta is the visit’s own parsed JSON metadata and includes external_user_id when the submitting page set it.

Authentication: Bearer token (ApiKeyAuth), scope read:visits.

Parameters

NameInTypeRequiredDescription
device_idquerystringNo
fromquerystring (date-time)No
toquerystring (date-time)No
domain_idquerystringNo
external_user_idquerystringNo
limitqueryintegerNoMinimum 1, maximum 200. Default 50.
cursorquerystringNo

Responses

StatusMeaningError codesContent
200A page of visits.application/json
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
visitsarray of objectYes
visits[]objectNo
visits[].idstringNo
visits[].deviceIdstringNo
visits[].domainIdstringNo
visits[].countrystring, nullableNo
visits[].citystring, nullableNo
visits[].metaobjectNoThe row’s own parsed JSON meta blob (e.g. external_user_id); shape is submitter-controlled and not locally validated.
visits[].createdAtstring (date-time)No
hasMorebooleanYes
nextCursorstring, nullableYes

Response example (200)

{
  "ok": true,
  "visits": [
    {
      "id": "example-id",
      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domainId": "dom_3f2a8c91d6e5f470",
      "country": "US",
      "city": "Istanbul",
      "meta": {},
      "createdAt": "2026-09-13T12:00:00.000Z"
    }
  ],
  "hasMore": true,
  "nextCursor": "cursor_000123"
}

Example request

curl

curl "https://collect.noxtica.com/v1/visits" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/visits', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/visits",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Export fingerprints as CSV or JSON

GET /v1/exports/fingerprints

Bulk-exports device fingerprint records for a date range. from and to are required and are validated for both shape and calendar (a malformed string or an impossible date such as 2026-02-30 is rejected) before being echoed into the CSV Content-Disposition filename.

Each request returns at most a fixed maximum number of rows. A capped page sets truncated: true (JSON) or the X-Noxtica-Export-Truncated: true header (CSV) and an opaque keyset next_cursor (JSON) or X-Noxtica-Export-Next-Cursor header (CSV) over (created_at, id) descending; request the next page with that cursor.

reason_codes is the published reason-code projection (empty unless reason-code output is enabled for your organisation) and is the last CSV column, so fixed-position consumers are unaffected.

Authentication: Bearer token (ApiKeyAuth), scope read:export.

Parameters

NameInTypeRequiredDescription
formatquerystringNoAllowed values: json, csv. Default json.
fromquerystringYesREQUIRED. YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, or ISO 8601 (optional ms/offset).
toquerystringYes
domain_idquerystringNo
sourcequerystringNoAllowed values: real, synthetic, all. Default real.
cursorquerystringNoOpaque keyset cursor from a prior response’s next_cursor. Omit for page 1.

Responses

StatusMeaningError codesContent
200The exported page, as a JSON envelope or a raw CSV body depending on format.application/json, text/csv
400Invalid source/Invalid format, missing from/to, or from and to must be YYYY-MM-DD or ISO 8601 datetime values.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
200X-Noxtica-Export-Next-Cursorstring
200X-Noxtica-Export-Truncatedstring
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
countintegerYes
limitintegerYes
truncatedbooleanYes
fromstringYes
tostringYes
next_cursorstringNo
fingerprintsarray of objectYes
fingerprints[]objectNo
fingerprints[].device_idstringNo
fingerprints[].domain_idstringNo
fingerprints[].scorenumber, nullableNo
fingerprints[].risk_levelstring, nullableNo
fingerprints[].flagsstringNoSemicolon-joined.
fingerprints[].reason_codesstringNoSemicolon-joined; empty unless reason-code output is enabled for your organisation.
fingerprints[].countrystringNo
fingerprints[].citystringNo
fingerprints[].created_atstring (date-time)No
fingerprints[].updated_atstring (date-time)No
fingerprints[].is_syntheticstringNoAllowed values: true, false.

Response example (200)

{
  "ok": true,
  "count": 1,
  "limit": 1,
  "truncated": true,
  "from": "example-from",
  "to": "example-to",
  "next_cursor": "cursor_000123",
  "fingerprints": [
    {
      "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domain_id": "dom_3f2a8c91d6e5f470",
      "score": 1,
      "risk_level": "low",
      "flags": "example-flags",
      "reason_codes": "example-reason_codes",
      "country": "US",
      "city": "Istanbul",
      "created_at": "2026-09-13T12:00:00.000Z",
      "updated_at": "2026-09-13T12:00:00.000Z",
      "is_synthetic": "true"
    }
  ]
}

Example request

curl

curl "https://collect.noxtica.com/v1/exports/fingerprints?from=example-from&to=example-to" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/exports/fingerprints?from=example-from&to=example-to', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/exports/fingerprints?from=example-from&to=example-to",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Export events as CSV or JSON

GET /v1/exports/events

Bulk-exports scored events for a date range. The contract is identical to GET /v1/exports/fingerprints: the same date validation, per-request row cap, and truncated / next_cursor pagination.

Authentication: Bearer token (ApiKeyAuth), scope read:export.

Parameters

NameInTypeRequiredDescription
formatquerystringNoAllowed values: json, csv. Default json.
fromquerystringYes
toquerystringYes
domain_idquerystringNo
sourcequerystringNoAllowed values: real, synthetic, all. Default real.
cursorquerystringNo

Responses

StatusMeaningError codesContent
200The exported page, as a JSON envelope or a raw CSV body depending on format.application/json, text/csv
400Invalid source/Invalid format, missing from/to, or invalid date shape/calendar.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
200X-Noxtica-Export-Next-Cursorstring
200X-Noxtica-Export-Truncatedstring
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
countintegerYes
limitintegerYes
truncatedbooleanYes
fromstringYes
tostringYes
next_cursorstringNo
eventsarray of objectYes
events[]objectNo
events[].idstringNo
events[].device_idstringNo
events[].domain_idstringNo
events[].scorenumber, nullableNo
events[].risk_levelstring, nullableNo
events[].reason_codesstringNoSemicolon-joined; empty unless reason-code output is enabled for your organisation.
events[].countrystringNo
events[].created_atstring (date-time)No
events[].is_syntheticstringNoAllowed values: true, false.

Response example (200)

{
  "ok": true,
  "count": 1,
  "limit": 1,
  "truncated": true,
  "from": "example-from",
  "to": "example-to",
  "next_cursor": "cursor_000123",
  "events": [
    {
      "id": "example-id",
      "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domain_id": "dom_3f2a8c91d6e5f470",
      "score": 1,
      "risk_level": "low",
      "reason_codes": "example-reason_codes",
      "country": "US",
      "created_at": "2026-09-13T12:00:00.000Z",
      "is_synthetic": "true"
    }
  ]
}

Example request

curl

curl "https://collect.noxtica.com/v1/exports/events?from=example-from&to=example-to" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/exports/events?from=example-from&to=example-to', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/exports/events?from=example-from&to=example-to",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Export visits as CSV or JSON

GET /v1/exports/visits

Bulk-exports visit records for a date range, with the same date validation, per-request row cap and pagination as the other exports. Visits have no synthetic partition, so there is no source parameter.

Authentication: Bearer token (ApiKeyAuth), scope read:export.

Parameters

NameInTypeRequiredDescription
formatquerystringNoAllowed values: json, csv. Default json.
fromquerystringYes
toquerystringYes
domain_idquerystringNo
cursorquerystringNo

Responses

StatusMeaningError codesContent
200The exported page, as a JSON envelope or a raw CSV body depending on format.application/json, text/csv
400Invalid format, missing from/to, or invalid date shape/calendar.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
200X-Noxtica-Export-Next-Cursorstring
200X-Noxtica-Export-Truncatedstring
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
countintegerYes
limitintegerYes
truncatedbooleanYes
fromstringYes
tostringYes
next_cursorstringNo
visitsarray of objectYes
visits[]objectNo
visits[].idstringNo
visits[].device_idstringNo
visits[].domain_idstringNo
visits[].countrystringNo
visits[].citystringNo
visits[].external_user_idstringNo
visits[].created_atstring (date-time)No

Response example (200)

{
  "ok": true,
  "count": 1,
  "limit": 1,
  "truncated": true,
  "from": "example-from",
  "to": "example-to",
  "next_cursor": "cursor_000123",
  "visits": [
    {
      "id": "example-id",
      "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "domain_id": "dom_3f2a8c91d6e5f470",
      "country": "US",
      "city": "Istanbul",
      "external_user_id": "example-external_user_id",
      "created_at": "2026-09-13T12:00:00.000Z"
    }
  ]
}

Example request

curl

curl "https://collect.noxtica.com/v1/exports/visits?from=example-from&to=example-to" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/exports/visits?from=example-from&to=example-to', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/exports/visits?from=example-from&to=example-to",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Stream scored events as JSON Lines

GET /v1/exports/scored-events

Streams scored events as newline-delimited JSON, newest first: one scored-event object per line, followed by a trailing _summary line. The stream is capped at a fixed maximum number of rows per request.

  • tier is coarser than gpuAttestationTier on GET /v1/device/{deviceId}: only a hardware-attested device maps to attested; everything else is suspicious.
  • band is one of critical, high, medium, low, minimal; an unrecognised stored value is reported as minimal.
  • reason_codes holds at most 64 entries and is empty unless reason-code output is enabled for your organisation.

This route validates the shape of from and to only, not calendar validity, unlike the JSON/CSV exports.

Authentication: Bearer token (ApiKeyAuth), scope read:export.

Parameters

NameInTypeRequiredDescription
fromquerystringYesREQUIRED. YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, or ISO 8601.
toquerystringYes
domain_idquerystringNo
cursorquerystringNoOpaque keyset cursor from a prior response’s next_cursor (in the trailing _summary line). No cursor param on page 1.

Responses

StatusMeaningError codesContent
200JSONL body: one scored-event object per line, then a trailing _summary line.application/x-ndjson
400Missing from/to, or a value not matching the accepted date shape (this route validates SHAPE only, not calendar validity, unlike the sibling JSON/CSV exports).invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
200X-Noxtica-Export-Next-Cursorstring
200X-Noxtica-Export-Truncatedstring
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/x-ndjson)

Type: string.

Example request

curl

curl "https://collect.noxtica.com/v1/exports/scored-events?from=example-from&to=example-to" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/exports/scored-events?from=example-from&to=example-to', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/exports/scored-events?from=example-from&to=example-to",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Read reason-code firing counts

GET /v1/emerging-threats

Returns per-reason-code firing counts and rates over a bounded lookback window, aggregated from the published reason-code catalogue. It reuses the read:export scope.

The report is disabled unless it is enabled for the deployment. When it is, the route does no warehouse work and answers a neutral 200 with {"available":false,"reason":"feature_unavailable","signals":[]}, so you can always probe it safely. A warehouse read fault degrades to an empty signals array and window_sessions: 0; this route never answers 500 for it.

Authentication: Bearer token (ApiKeyAuth), scope read:export.

Parameters

NameInTypeRequiredDescription
windowqueryintegerNoLookback hours; any other value silently falls back to 24. Allowed values: 1, 6, 24, 168, 720. Default 24.

Responses

StatusMeaningError codesContent
200The firing-count report, or the feature-disabled neutral empty state.application/json
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
availablebooleanYes
reasonstringNoAllowed values: feature_unavailable.
window_hoursintegerYes
window_sessionsintegerNoPresent only when available is true.
signalsarray of objectYes
signals[]objectNo
signals[].reason_codestringNo
signals[].domainstringNo
signals[].labelstringNo
signals[].firing_countintegerNo
signals[].firing_ratenumber, nullableNonull when window_sessions is below the 20-session display floor.
countintegerYes

Response example (200)

{
  "ok": true,
  "available": true,
  "reason": "feature_unavailable",
  "window_hours": 1,
  "window_sessions": 1,
  "signals": [
    {
      "reason_code": "example-reason_code",
      "domain": "app.example.com",
      "label": "example-label",
      "firing_count": 1,
      "firing_rate": 1
    }
  ],
  "count": 1
}

Example request

curl

curl "https://collect.noxtica.com/v1/emerging-threats" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/emerging-threats', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/emerging-threats",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Fetch the key that opens Sealed Client Results

GET /v1/sealed-results/key

Returns your organisation’s symmetric key for opening Sealed Client Results envelopes. The key is derived on demand and never stored.

keyVersion is optional. Each sealed envelope carries the cleartext kv (key version) it was sealed under, and this route serves any past version that has not been revoked, so rotation never orphans an archived envelope. expiresAt is present only when a key lifetime is configured.

  • 404 sealed_key_version_unavailable — keyVersion is not a positive integer or is newer than the current version. No key material is returned.
  • 403 — the key lacks read:sealed_results, or the key is revoked for this organisation and version.
  • 500 server_misconfigured — sealed results are not provisioned for this deployment; this is distinct from an authentication failure.

Authentication: Bearer token (ApiKeyAuth), scope read:sealed_results.

Parameters

NameInTypeRequiredDescription
keyVersionquerystringNoKey version to fetch — the kv a Sealed Client Result envelope carries. Omitted = the current version (the response is unchanged). A past version is served from the server’s master ring until it is REVOKED for the tenant (403, as for the current version). A malformed or future version answers 404 sealed_key_version_unavailable. Pattern ^[1-9][0-9]{0,8}$.

Responses

StatusMeaningError codesContent
200The tenant’s sealed-results key material.application/json
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403API key does not have read:sealed_results scope, OR the sealed-results key is revoked for this tenant/version (sealed-results key revoked for this tenant/version).invalid_requestapplication/json
404sealed_key_version_unavailable — the requested keyVersion is not a positive integer, or is newer than the current key version. Explicit (never a 500); no key material is returned.sealed-results key version unavailable, sealed_key_version_unavailableapplication/json
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server error, server_misconfiguredapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
keyVersionstringYes
keystringYesbase64-encoded raw derived key.
algstringYes
envelopestringYesAllowed values: noxtica-sealed-v1.
expiresAtintegerNoAbsolute epoch-ms expiry hint; present only when a TTL is configured.

Response example (200)

{
  "ok": true,
  "keyVersion": "example-keyVersion",
  "key": "example-key",
  "alg": "example-alg",
  "envelope": "noxtica-sealed-v1",
  "expiresAt": 1768435200
}

Example request

curl

curl "https://collect.noxtica.com/v1/sealed-results/key" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/sealed-results/key', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/sealed-results/key",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

List your organisation’s ground-truth labels

GET /v1/labels

Lists the labels your organisation has written with POST /v1/labels, with optional device_id and label filters and a keyset cursor over (created_at, id) (the same opaque cursor shape as GET /v1/events). It reuses the read:device scope; there is no separate read-labels scope.

Authentication: Bearer token (ApiKeyAuth), scope read:device.

Parameters

NameInTypeRequiredDescription
device_idquerystringNo
labelquerystringNoAllowed values: bot, human, fraud, legit, unknown.
limitqueryintegerNoMinimum 1, maximum 200. Default 50.
cursorquerystringNo

Responses

StatusMeaningError codesContent
200A page of labels.application/json
400Invalid label. Expected one of: bot, human, fraud, legit, unknown.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
labelsarray of objectYes
labels[]objectNo
labels[].idstring (uuid)No
labels[].deviceIdstringNo
labels[].eventIdstring, nullableNo
labels[].labelstringNoAllowed values: bot, human, fraud, legit, unknown.
labels[].sourcestringNo
labels[].notestring, nullableNo
labels[].createdAtstring (date-time)No
labels[].updatedAtstring (date-time)No
hasMorebooleanYes
nextCursorstring, nullableYes

Response example (200)

{
  "ok": true,
  "labels": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
      "eventId": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
      "label": "bot",
      "source": "example-source",
      "note": "created via API",
      "createdAt": "2026-09-13T12:00:00.000Z",
      "updatedAt": "2026-09-13T12:00:00.000Z"
    }
  ],
  "hasMore": true,
  "nextCursor": "cursor_000123"
}

Example request

curl

curl "https://collect.noxtica.com/v1/labels" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/labels', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/labels",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Write a ground-truth label for a device

POST /v1/labels

Records a confirmed fraud, legitimate or other label for a device, optionally scoped to one event, to calibrate scoring. The write is an upsert: repeating the same (device_id, event_id) updates label, source, note and updated_at on the existing row instead of creating a duplicate.

The body accepts only device_id, label, event_id, note and source; any other key is rejected with 400 Unknown field. label must be one of bot, human, fraud, legit, unknown.

Authentication: Bearer token (ApiKeyAuth), scope write:labels.

Request body

Content type application/json, required.

FieldTypeRequiredDescription
device_idstringYesAt most 256 characters.
labelstringYesAllowed values: bot, human, fraud, legit, unknown.
event_idstring, nullableNoOptional; blank/whitespace-only normalizes to NULL (collapses onto the device-level idempotency slot). At most 256 characters.
notestring, nullableNoAt most 1024 characters.
sourcestringNoTruncated to 64 chars; defaults to ‘api’ when omitted/blank. At most 64 characters. Default api.

Responses

StatusMeaningError codesContent
200The upserted (inserted or updated) label row.application/json
400Unknown body field, missing/oversized device_id, invalid label, or an oversized event_id/note.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
413The request body exceeded this route’s byte cap.body_too_largeapplication/json ErrorEnvelope
415Content-Type must be application/json.invalid_requestapplication/json ErrorEnvelope
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
labelobjectYes
label.idstring (uuid)No
label.deviceIdstringNo
label.eventIdstring, nullableNo
label.labelstringNoAllowed values: bot, human, fraud, legit, unknown.
label.sourcestringNo
label.notestring, nullableNo
label.createdAtstring (date-time)No
label.updatedAtstring (date-time)No

Response example (200)

{
  "ok": true,
  "label": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
    "eventId": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
    "label": "bot",
    "source": "example-source",
    "note": "created via API",
    "createdAt": "2026-09-13T12:00:00.000Z",
    "updatedAt": "2026-09-13T12:00:00.000Z"
  }
}

Example request

curl

curl -X POST "https://collect.noxtica.com/v1/labels" \
  -H "Authorization: Bearer $NOXTICA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
  "label": "bot",
  "event_id": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
  "note": "created via API",
  "source": "api"
}'

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/labels', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    device_id: 'dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d',
    label: 'bot',
    event_id: 'evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70',
    note: 'created via API',
    source: 'api',
  }),
});
console.log(response.status, await response.text());

Python (standard library)

import json
import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/labels",
    data=json.dumps({
        "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
        "label": "bot",
        "event_id": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
        "note": "created via API",
        "source": "api",
    }).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
        "Content-Type": "application/json",
    },
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Generate a batch of synthetic devices

POST /v1/generator/fingerprints

Generates count synthetic devices, each with eventsPerDevice events, derived deterministically from real template fingerprints, for testing and load. Read them back with source=synthetic.

The call is idempotent on (domain_id, seed): a repeated identical request returns the same existing batch with isExisting: true and HTTP 200; a new batch answers 201. domain_id must be an active domain of your organisation, otherwise the route answers 404.

Authentication: Bearer token (ApiKeyAuth), scope write:generate.

Request body

Content type application/json, required.

FieldTypeRequiredDescription
domain_idstringYes
seedstringYesIdempotency key for the whole batch.
countintegerNoCoerced via Number(); non-positive/non-finite falls back to 10. Minimum 1, maximum 100. Default 10.
eventsPerDeviceintegerNoMinimum 1, maximum 10. Default 3.
sourceFromstringNo
sourceTostringNo
sourceLimitintegerNoMaximum 500. Default 200.
scrubIPsbooleanNoAny value other than the literal false is treated as true. Default true.

Responses

StatusMeaningError codesContent
200The existing batch, when seed already matches a committed batch for this (tenant, domain).application/json
201A newly-committed batch.application/json
400domain_id and seed are required, or No template fingerprints found in the specified range.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
404Domain not found or does not belong to tenant.invalid_requestapplication/json ErrorEnvelope
413The request body exceeded this route’s byte cap.body_too_largeapplication/json ErrorEnvelope
415Content-Type must be application/json.invalid_requestapplication/json ErrorEnvelope
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
isExistingbooleanYes
batchIdstringYes
seedstringYes
tenantIdstringYes
domainIdstringYes
deviceIdsarray of stringYes
totalDevicesintegerYes
totalEventsintegerYes
createdAtstring (date-time)Yes

Response example (200)

{
  "ok": true,
  "isExisting": true,
  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
  "seed": "seed-01",
  "tenantId": "tenant_42",
  "domainId": "dom_3f2a8c91d6e5f470",
  "deviceIds": [
    "example-deviceIds"
  ],
  "totalDevices": 1,
  "totalEvents": 1,
  "createdAt": "2026-09-13T12:00:00.000Z"
}

Response fields (201, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
isExistingbooleanYes
batchIdstringYes
seedstringYes
tenantIdstringYes
domainIdstringYes
deviceIdsarray of stringYes
totalDevicesintegerYes
totalEventsintegerYes
createdAtstring (date-time)Yes

Response example (201)

{
  "ok": true,
  "isExisting": true,
  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
  "seed": "seed-01",
  "tenantId": "tenant_42",
  "domainId": "dom_3f2a8c91d6e5f470",
  "deviceIds": [
    "example-deviceIds"
  ],
  "totalDevices": 1,
  "totalEvents": 1,
  "createdAt": "2026-09-13T12:00:00.000Z"
}

Example request

curl

curl -X POST "https://collect.noxtica.com/v1/generator/fingerprints" \
  -H "Authorization: Bearer $NOXTICA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "domain_id": "dom_3f2a8c91d6e5f470",
  "seed": "seed-01",
  "count": 10,
  "eventsPerDevice": 3,
  "sourceFrom": "example-sourceFrom",
  "sourceTo": "example-sourceTo",
  "sourceLimit": 200,
  "scrubIPs": true
}'

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/generator/fingerprints', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    domain_id: 'dom_3f2a8c91d6e5f470',
    seed: 'seed-01',
    count: 10,
    eventsPerDevice: 3,
    sourceFrom: 'example-sourceFrom',
    sourceTo: 'example-sourceTo',
    sourceLimit: 200,
    scrubIPs: true,
  }),
});
console.log(response.status, await response.text());

Python (standard library)

import json
import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/generator/fingerprints",
    data=json.dumps({
        "domain_id": "dom_3f2a8c91d6e5f470",
        "seed": "seed-01",
        "count": 10,
        "eventsPerDevice": 3,
        "sourceFrom": "example-sourceFrom",
        "sourceTo": "example-sourceTo",
        "sourceLimit": 200,
        "scrubIPs": True,
    }).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
        "Content-Type": "application/json",
    },
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Generate one seeded synthetic device

POST /v1/generator/fingerprint

Generates one synthetic device from a filtered selection of real template fingerprints. It is idempotent on the derived seed key: a repeated request returns the existing device unchanged with isExisting: true and HTTP 200; a new device answers 201.

json_filters, when present, constrain the candidate templates by JSONPath-style equality against the stored fingerprint, score and collector fields. Domain ownership, scope and body rules are the same as for POST /v1/generator/fingerprints.

Authentication: Bearer token (ApiKeyAuth), scope write:generate.

Request body

Content type application/json, required.

FieldTypeRequiredDescription
domain_idstringYes
seedstringYes
platformstringNo
risk_levelstringNo
countrystringNo
languagestringNo
timezonestringNo
score_minnumberNo
score_maxnumberNo
json_filtersarray of objectNoNormalized/hashed into the deterministic seed key alongside seed.
json_filters[]objectNo
json_filters[].sourcestringYesAllowed values: fingerprint, score, cf.
json_filters[].pathstringYesA JSONPath-style equality filter, e.g. $.signals.webgl.vendor.
json_filters[].valueanyNo
sourceFromstringNo
sourceTostringNo
sourceLimitintegerNoMaximum 500. Default 200.
scrubIPsbooleanNoDefault true.

Responses

StatusMeaningError codesContent
200The existing seeded fingerprint (returned unchanged, Cache-Control: no-store).application/json
201A newly-committed seeded fingerprint.application/json
400domain_id and seed are required, or No template fingerprints found matching the specified filters.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
404Domain not found or does not belong to tenant.invalid_requestapplication/json ErrorEnvelope
413The request body exceeded this route’s byte cap.body_too_largeapplication/json ErrorEnvelope
415Content-Type must be application/json.invalid_requestapplication/json ErrorEnvelope
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
200Cache-Controlstring
201Cache-Controlstring

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
isExistingbooleanYes
seedstringYes
filtersobjectYesThe normalized template filters echoed back.
tenantIdstringYes
domainIdstringYes
batchIdstringYes
deviceIdstringYes
templateEventIdstringYes
fingerprintobjectYesThe stored synthetic fingerprint blob (template-derived; shape not locally schema-validated).
scoreobjectYesThe stored score blob copied verbatim from the selected template.
cfobjectYesThe stored Cloudflare-geo blob, IP-scrubbed when scrubIPs is true.
createdAtstring (date-time)Yes
updatedAtstring (date-time)Yes

Response example (200)

{
  "ok": true,
  "isExisting": true,
  "seed": "seed-01",
  "filters": {},
  "tenantId": "tenant_42",
  "domainId": "dom_3f2a8c91d6e5f470",
  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
  "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
  "templateEventId": "example-templateEventId",
  "fingerprint": {},
  "score": {},
  "cf": {},
  "createdAt": "2026-09-13T12:00:00.000Z",
  "updatedAt": "2026-09-13T12:00:00.000Z"
}

Response fields (201, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
isExistingbooleanYes
seedstringYes
filtersobjectYesThe normalized template filters echoed back.
tenantIdstringYes
domainIdstringYes
batchIdstringYes
deviceIdstringYes
templateEventIdstringYes
fingerprintobjectYesThe stored synthetic fingerprint blob (template-derived; shape not locally schema-validated).
scoreobjectYesThe stored score blob copied verbatim from the selected template.
cfobjectYesThe stored Cloudflare-geo blob, IP-scrubbed when scrubIPs is true.
createdAtstring (date-time)Yes
updatedAtstring (date-time)Yes

Response example (201)

{
  "ok": true,
  "isExisting": true,
  "seed": "seed-01",
  "filters": {},
  "tenantId": "tenant_42",
  "domainId": "dom_3f2a8c91d6e5f470",
  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
  "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
  "templateEventId": "example-templateEventId",
  "fingerprint": {},
  "score": {},
  "cf": {},
  "createdAt": "2026-09-13T12:00:00.000Z",
  "updatedAt": "2026-09-13T12:00:00.000Z"
}

Example request

curl

curl -X POST "https://collect.noxtica.com/v1/generator/fingerprint" \
  -H "Authorization: Bearer $NOXTICA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "domain_id": "dom_3f2a8c91d6e5f470",
  "seed": "seed-01",
  "platform": "example-platform",
  "risk_level": "low",
  "country": "US",
  "language": "example-language",
  "timezone": "example-timezone",
  "score_min": 1,
  "score_max": 1,
  "json_filters": [
    {
      "source": "fingerprint",
      "path": "/v1/kyc/verify",
      "value": "example-value"
    }
  ],
  "sourceFrom": "example-sourceFrom",
  "sourceTo": "example-sourceTo",
  "sourceLimit": 200,
  "scrubIPs": true
}'

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/generator/fingerprint', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    domain_id: 'dom_3f2a8c91d6e5f470',
    seed: 'seed-01',
    platform: 'example-platform',
    risk_level: 'low',
    country: 'US',
    language: 'example-language',
    timezone: 'example-timezone',
    score_min: 1,
    score_max: 1,
    json_filters: [
      {
        source: 'fingerprint',
        path: '/v1/kyc/verify',
        value: 'example-value',
      },
    ],
    sourceFrom: 'example-sourceFrom',
    sourceTo: 'example-sourceTo',
    sourceLimit: 200,
    scrubIPs: true,
  }),
});
console.log(response.status, await response.text());

Python (standard library)

import json
import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/generator/fingerprint",
    data=json.dumps({
        "domain_id": "dom_3f2a8c91d6e5f470",
        "seed": "seed-01",
        "platform": "example-platform",
        "risk_level": "low",
        "country": "US",
        "language": "example-language",
        "timezone": "example-timezone",
        "score_min": 1,
        "score_max": 1,
        "json_filters": [
            {
                "source": "fingerprint",
                "path": "/v1/kyc/verify",
                "value": "example-value",
            },
        ],
        "sourceFrom": "example-sourceFrom",
        "sourceTo": "example-sourceTo",
        "sourceLimit": 200,
        "scrubIPs": True,
    }).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
        "Content-Type": "application/json",
    },
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Read a subject’s behavioral baseline

GET /v1/behavioral/subjects/{subjectRef}

Reads a subject’s current behavioral-baseline enrollment and its latest drift snapshot. subjectRef is your raw end-user account id: it is never stored, logged or echoed, only keyed-hashed server-side before any lookup.

Not enabled by default: the whole /v1/behavioral/* family answers the GatedNotFound 404 unless behavioral baselines are enabled for the deployment, and only then is the read:behavioral scope checked.

Authentication: Bearer token (ApiKeyAuth), scope read:behavioral.

Parameters

NameInTypeRequiredDescription
subjectRefpathstringYesThe tenant’s raw end-user account id (hashed server-side; never stored as given). At most 256 characters.

Responses

StatusMeaningError codesContent
200The subject’s baseline enrollment + latest drift.application/json
400Invalid subjectRef — empty or over 256 chars.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
404Subject not found (no current snapshot exists), or V1 endpoint not found when behavioral baselines are not enabled for the deployment.invalid_requestapplication/json ErrorEnvelope
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
subjectobjectYes
subject.enrollmentStatusstringNoA persisted value outside the closed set clamps to learning. Allowed values: learning, active.
subject.sampleCountintegerNo
subject.attestationProvenanceobjectNo
subject.attestationProvenance.gpu_attestedintegerNo
subject.attestationProvenance.sealedintegerNo
subject.attestationProvenance.unattestedintegerNo
subject.deviationnumber, nullableNo
subject.familiesobject, nullableNo
subject.families.pointernumber, nullableNo
subject.families.keystrokenumber, nullableNo
subject.families.cadencenumber, nullableNo
subject.lastDriftAtstring (date-time), nullableNo

Response example (200)

{
  "ok": true,
  "subject": {
    "enrollmentStatus": "learning",
    "sampleCount": 1,
    "attestationProvenance": {
      "gpu_attested": 1,
      "sealed": 1,
      "unattested": 1
    },
    "deviation": 1,
    "families": {
      "pointer": 1,
      "keystroke": 1,
      "cadence": 1
    },
    "lastDriftAt": "2026-09-13T12:00:00.000Z"
  }
}

Example request

curl

curl "https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Erase a subject’s behavioral baseline

DELETE /v1/behavioral/subjects/{subjectRef}

Erases a subject’s behavioral baseline, for data-subject erasure requests. Live profile state is erased first, then the stored snapshots and drift projections are hard-deleted. If the live-state erase fails the route answers 502 with {"ok":false,"profileErased":false,...} instead of a false 200, because a surviving profile could otherwise re-flush the erased snapshot; the call is safe to retry. Erasing an unknown or already-erased subject is idempotent and answers 200 {"deleted":{"snapshots":0,"driftEvents":0}}.

This erases account-scoped (acct:) subjects only. Device-scoped baselines and the raw behavioral tracks need the separate per-device erasure path in the Backoffice, so a subject with both needs both paths. Availability is the same as for GET /v1/behavioral/subjects/{subjectRef}.

Authentication: Bearer token (ApiKeyAuth), scope erase:behavioral.

Parameters

NameInTypeRequiredDescription
subjectRefpathstringYesAt most 256 characters.

Responses

StatusMeaningError codesContent
200Erasure completed (or was already a no-op for an unknown subject).application/json
400Invalid subjectRef — empty or over 256 chars.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
404Subject not found, or V1 endpoint not found when behavioral baselines are not enabled for the deployment.invalid_requestapplication/json ErrorEnvelope
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope
502{ ok:false, profileErased:false, deleted, error: 'behavioral profile durable-object erase failed — retry (idempotent)' } — the erase call is safe to retry.invalid_requestapplication/json

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
profileErasedbooleanYesAllowed values: true.
deletedobjectYes
deleted.snapshotsintegerNo
deleted.driftEventsintegerNo

Response example (200)

{
  "ok": true,
  "profileErased": true,
  "deleted": {
    "snapshots": 1,
    "driftEvents": 1
  }
}

Example request

curl

curl -X DELETE "https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="DELETE",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

Read a subject’s drift-event history

GET /v1/behavioral/subjects/{subjectRef}/timeline

Reads a subject’s drift events, newest first. The row cap is clamped to 1–100 and there is no pagination cursor on this route. subjectRef handling and availability are the same as for GET /v1/behavioral/subjects/{subjectRef}.

Authentication: Bearer token (ApiKeyAuth), scope read:behavioral.

Parameters

NameInTypeRequiredDescription
subjectRefpathstringYesAt most 256 characters.
limitqueryintegerNoMinimum 1, maximum 100. Default 50.

Responses

StatusMeaningError codesContent
200The subject’s drift-event timeline.application/json
400Invalid subjectRef — empty or over 256 chars.invalid_requestapplication/json ErrorEnvelope
401The Authorization: Bearer sk_... header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.invalid_api_keyapplication/json InvalidApiKeyError
403The API key is valid but does not carry the scope this operation requires; error names the missing scope.API key does not have read:device scopeapplication/json ScopeForbiddenError
404Subject not found, or V1 endpoint not found when behavioral baselines are not enabled for the deployment.invalid_requestapplication/json ErrorEnvelope
429Rate limit exceeded. Wait Retry-After seconds (also retryAfter in the body) before retrying; the response carries no other rate-limit headers.Rate limit exceededapplication/json
500Unexpected server fault. Retry with backoff and quote requestId to support if it persists.Internal server errorapplication/json ErrorEnvelope

Response headers

StatusHeaderTypeDescription
429Retry-AfterintegerSeconds until the bucket allows another request.

Response fields (200, application/json)

FieldTypeAlways returnedDescription
okbooleanYesAllowed values: true.
eventsarray of objectYes
events[]objectNo
events[].deviationnumber, nullableNo
events[].familiesobject, nullableNo
events[].families.pointernumber, nullableNo
events[].families.keystrokenumber, nullableNo
events[].families.cadencenumber, nullableNo
events[].attestationstring, nullableNo
events[].channelstring, nullableNo
events[].createdAtstring (date-time)No
countintegerYes

Response example (200)

{
  "ok": true,
  "events": [
    {
      "deviation": 1,
      "families": {
        "pointer": 1,
        "keystroke": 1,
        "cadence": 1
      },
      "attestation": "example-attestation",
      "channel": "example-channel",
      "createdAt": "2026-09-13T12:00:00.000Z"
    }
  ],
  "count": 1
}

Example request

curl

curl "https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef/timeline" \
  -H "Authorization: Bearer $NOXTICA_API_KEY"

Node.js (global fetch, Node 18 or later)

const response = await fetch('https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef/timeline', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.NOXTICA_API_KEY}`,
  },
});
console.log(response.status, await response.text());

Python (standard library)

import os
import urllib.request

request = urllib.request.Request(
    "https://collect.noxtica.com/v1/behavioral/subjects/example-subjectRef/timeline",
    headers={
        "Authorization": f"Bearer {os.environ['NOXTICA_API_KEY']}",
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())

This page is generated from the Noxtica OpenAPI specification release v0.4.0: v1.yaml version 1.3.0-2026-10-27 (SHA-256 3fd15257a022). Do not edit it by hand.