Skip to content
Sections

Audit & SIEM

Ingest a signed external audit event batch

POST/organizations/{organizationId}/audit/inbound-sources/{sourceKey}/events

Accepts 1–500 newline-delimited OCSF JSON events for an active organization source. Hallify verifies the HMAC over the exact raw NDJSON bytes, enforces the timestamp and replay window, validates every event, and persists the accepted batch as audit evidence. Hallify HMAC profile audit-inbound uses HMAC-SHA256. Canonical input: unixSeconds + "." + raw UTF-8 NDJSON. Send x-hallify-timestamp as unix-seconds; timestamps outside ±300 seconds are stale. Send x-hallify-signature as lowercase hexadecimal; comparison is timing-safe. Secret handling: Decode the issued base64url secret into exactly 32 raw bytes before signing. Accepted Content-Type: application/x-ndjson, application/ndjson. Malformed input: Malformed signature metadata returns 401 AUDIT_INGRESS_SIGNATURE_INVALID; malformed NDJSON returns 400. Stale input: A timestamp outside the 300-second window returns 401 AUDIT_INGRESS_SIGNATURE_INVALID. Repeated delivery: A repeated signature is rejected with 409 AUDIT_INGRESS_REPLAY.

Authentication

x-hallify-signature: <HALLIFY_SIGNATURE>

HMAC-SHA256 signature credential. Each operation documents its exact protocol through x-hallify-hmac metadata and the operation description.

Connection guide

Parameters

organizationIdPath · Required

Organization tenant whose resources and policies are addressed; membership, permission, and tenant-isolation checks use this identifier.

string · uuid
Full definition
{
  "type": "string",
  "format": "uuid",
  "example": "9b6163a8-afea-4877-818b-8e2ae28a2845"
}
sourceKeyPath · Required

Stable key of the configured audit-ingress source whose HMAC secret verifies this delivery.

string
Full definition
{
  "type": "string",
  "example": "example"
}
x-hallify-timestampHeader · Required

unix-seconds timestamp; accepted clock skew is ±300 seconds.

string
Full definition
{
  "type": "string",
  "example": "example"
}

Request body

Required

Raw UTF-8 OCSF NDJSON batch. The exact raw bytes are part of the HMAC canonical input.

application/x-ndjson

string
Full definition
{
  "type": "string",
  "description": "Between 1 and 500 OCSF JSON objects, one event per line, with a maximum raw request size of 2 MB.",
  "example": "{\"class_uid\":1001,\"activity_id\":1}\n"
}

application/ndjson

string
Full definition
{
  "type": "string",
  "description": "Between 1 and 500 OCSF JSON objects, one event per line, with a maximum raw request size of 2 MB.",
  "example": "{\"class_uid\":1001,\"activity_id\":1}\n"
}

Responses

201Accepted batch identifier and counts for ingested or deduplicated audit events.
AuditIngestionResultDto
Full definition
{
  "$ref": "#/components/schemas/AuditIngestionResultDto"
}
Example response · 201 · application/json
{
  "batchId": "example-id",
  "accepted": 0,
  "deduplicated": 0,
  "events": [
    {
      "id": "64edc395-c85f-4e3b-8e3a-d593a4973acc",
      "receivedAt": "2026-01-15T12:00:00.000Z",
      "deduplicated": true
    }
  ]
}
400Malformed NDJSON batch or invalid audit event payload
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 400 · application/json
{
  "statusCode": 400,
  "error": "errors:http.badRequest",
  "code": "HTTP_BAD_REQUEST",
  "message": "errors:http.badRequest",
  "translationKey": "errors:http.badRequest"
}
401Invalid, malformed, or stale audit HMAC signature
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 401 · application/json
{
  "statusCode": 401,
  "error": "errors:http.unauthorized",
  "code": "HTTP_UNAUTHORIZED",
  "message": "errors:http.unauthorized",
  "translationKey": "errors:http.unauthorized"
}
404Active inbound audit source was not found
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 404 · application/json
{
  "statusCode": 404,
  "error": "errors:http.notFound",
  "code": "HTTP_NOT_FOUND",
  "message": "errors:http.notFound",
  "translationKey": "errors:http.notFound"
}
409Signed audit request was already processed
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 409 · application/json
{
  "statusCode": 409,
  "error": "errors:http.conflict",
  "code": "HTTP_CONFLICT",
  "message": "errors:http.conflict",
  "translationKey": "errors:http.conflict"
}
503Audit signing secret could not be decrypted
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 503 · application/json
{
  "statusCode": 503,
  "error": "errors:http.serviceUnavailable",
  "code": "HTTP_SERVICE_UNAVAILABLE",
  "message": "errors:http.serviceUnavailable",
  "translationKey": "errors:http.serviceUnavailable"
}

Schemas

AuditIngestionResultDto

Accepted batch identifier and counts for ingested or deduplicated audit events.

batchIdRequired

Opaque identifier for batch associated with audit inbound ingestion ingest; clients must not assume UUID syntax.

string
Full definition
{
  "type": "string",
  "description": "Opaque identifier for batch associated with audit inbound ingestion ingest; clients must not assume UUID syntax.",
  "example": "example-id"
}
acceptedRequired

Whole-number accepted recorded for audit inbound ingestion ingest. Accepted values enforce minimum 0.

integer
Full definition
{
  "type": "integer",
  "minimum": 0,
  "description": "Whole-number accepted recorded for audit inbound ingestion ingest. Accepted values enforce minimum 0.",
  "example": 0
}
deduplicatedRequired

Whole-number deduplicated recorded for audit inbound ingestion ingest. Accepted values enforce minimum 0.

integer
Full definition
{
  "type": "integer",
  "minimum": 0,
  "description": "Whole-number deduplicated recorded for audit inbound ingestion ingest. Accepted values enforce minimum 0.",
  "example": 0
}
eventsRequired

Events that compose the corresponding events section of audit inbound ingestion ingest.

array
Full definition
{
  "type": "array",
  "items": {
    "type": "object",
    "required": [
      "id",
      "receivedAt",
      "deduplicated"
    ],
    "properties": {
      "id": {
        "type": "string",
        "format": "uuid",
        "description": "Hallify UUID identifying audit inbound ingestion ingest events item.",
        "example": "64edc395-c85f-4e3b-8e3a-d593a4973acc"
      },
      "receivedAt": {
        "type": "string",
        "format": "date-time",
        "description": "RFC 3339 timestamp for received at; offsets represent the same absolute instant.",
        "example": "2026-01-15T12:00:00.000Z"
      },
      "deduplicated": {
        "type": "boolean",
        "description": "Whether the inbound audit event matched an event already accepted under the source replay rules.",
        "example": true
      }
    },
    "example": {
      "id": "64edc395-c85f-4e3b-8e3a-d593a4973acc",
      "receivedAt": "2026-01-15T12:00:00.000Z",
      "deduplicated": true
    }
  },
  "description": "Events that compose the corresponding events section of audit inbound ingestion ingest.",
  "example": [
    {
      "id": "64edc395-c85f-4e3b-8e3a-d593a4973acc",
      "receivedAt": "2026-01-15T12:00:00.000Z",
      "deduplicated": true
    }
  ]
}
Full definition
{
  "type": "object",
  "required": [
    "batchId",
    "accepted",
    "deduplicated",
    "events"
  ],
  "properties": {
    "batchId": {
      "type": "string",
      "description": "Opaque identifier for batch associated with audit inbound ingestion ingest; clients must not assume UUID syntax.",
      "example": "example-id"
    },
    "accepted": {
      "type": "integer",
      "minimum": 0,
      "description": "Whole-number accepted recorded for audit inbound ingestion ingest. Accepted values enforce minimum 0.",
      "example": 0
    },
    "deduplicated": {
      "type": "integer",
      "minimum": 0,
      "description": "Whole-number deduplicated recorded for audit inbound ingestion ingest. Accepted values enforce minimum 0.",
      "example": 0
    },
    "events": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "receivedAt",
          "deduplicated"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Hallify UUID identifying audit inbound ingestion ingest events item.",
            "example": "64edc395-c85f-4e3b-8e3a-d593a4973acc"
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp for received at; offsets represent the same absolute instant.",
            "example": "2026-01-15T12:00:00.000Z"
          },
          "deduplicated": {
            "type": "boolean",
            "description": "Whether the inbound audit event matched an event already accepted under the source replay rules.",
            "example": true
          }
        },
        "example": {
          "id": "64edc395-c85f-4e3b-8e3a-d593a4973acc",
          "receivedAt": "2026-01-15T12:00:00.000Z",
          "deduplicated": true
        }
      },
      "description": "Events that compose the corresponding events section of audit inbound ingestion ingest.",
      "example": [
        {
          "id": "64edc395-c85f-4e3b-8e3a-d593a4973acc",
          "receivedAt": "2026-01-15T12:00:00.000Z",
          "deduplicated": true
        }
      ]
    }
  },
  "description": "Accepted batch identifier and counts for ingested or deduplicated audit events.",
  "example": {
    "batchId": "example-id",
    "accepted": 0,
    "deduplicated": 0,
    "events": [
      {
        "id": "64edc395-c85f-4e3b-8e3a-d593a4973acc",
        "receivedAt": "2026-01-15T12:00:00.000Z",
        "deduplicated": true
      }
    ]
  }
}
TranslatedErrorDto

Stable error envelope emitted by the global HTTP exception boundary. Domain-specific machine data, when present, is nested under details.

statusCodeRequired

HTTP status code repeated from the response.

integer
Full definition
{
  "type": "integer",
  "description": "HTTP status code repeated from the response.",
  "example": 400
}
errorRequired

Translation key for the HTTP category, such as errors:http.conflict. The specific cause is identified by code and translationKey.

string
Full definition
{
  "type": "string",
  "description": "Translation key for the HTTP category, such as errors:http.conflict. The specific cause is identified by code and translationKey.",
  "example": "errors.request.invalid"
}
codeRequired

Stable machine-readable domain code, or an HTTP_* fallback when no domain code is provided. Branch on this field and the HTTP status; localized wording never controls retries or business decisions.

string
Full definition
{
  "type": "string",
  "example": "HTTP_BAD_REQUEST",
  "description": "Stable machine-readable domain code, or an HTTP_* fallback when no domain code is provided. Branch on this field and the HTTP status; localized wording never controls retries or business decisions."
}
messageRequired

Translation key, identical to translationKey. The API does not return localized display text. Resolve the key and translationValues in the consuming application.

string
Full definition
{
  "type": "string",
  "example": "errors:http.badRequest",
  "description": "Translation key, identical to translationKey. The API does not return localized display text. Resolve the key and translationValues in the consuming application."
}
translationKeyRequired

Canonical translation key, identical to message. Status-specific errors:http.* keys cover unspecified failures. Public keys and EN/RU explanations are listed in Developers; unknown keys require a localized client fallback.

string
Full definition
{
  "type": "string",
  "example": "errors:http.badRequest",
  "description": "Canonical translation key, identical to message. Status-specific errors:http.* keys cover unspecified failures. Public keys and EN/RU explanations are listed in Developers; unknown keys require a localized client fallback."
}
translationValuesOptional

Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.

object
Full definition
{
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "type": "string",
        "example": "example"
      },
      {
        "type": "number",
        "example": 0
      },
      {
        "type": "boolean",
        "example": true
      }
    ],
    "example": "example"
  },
  "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
  "example": {
    "exampleKey": "example"
  }
}
validationErrorsOptional

Field validation failures with translation keys and stable validator codes. Submitted values and raw validator text are not included.

array
Full definition
{
  "description": "Field validation failures with translation keys and stable validator codes. Submitted values and raw validator text are not included.",
  "type": "array",
  "items": {
    "$ref": "#/components/schemas/ValidationErrorDto"
  },
  "example": [
    {
      "field": "email",
      "translationKey": "validation:isEmail",
      "code": "isEmail",
      "message": "validation:isEmail"
    }
  ]
}
detailsOptional

Optional domain-specific blocker or validation details

oneOf
Full definition
{
  "description": "Optional domain-specific blocker or validation details",
  "oneOf": [
    {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": [
        "example"
      ]
    },
    {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": {
        "exampleKey": "example"
      }
    }
  ],
  "example": [
    "example"
  ]
}
Full definition
{
  "type": "object",
  "properties": {
    "statusCode": {
      "type": "integer",
      "description": "HTTP status code repeated from the response.",
      "example": 400
    },
    "error": {
      "type": "string",
      "description": "Translation key for the HTTP category, such as errors:http.conflict. The specific cause is identified by code and translationKey.",
      "example": "errors.request.invalid"
    },
    "code": {
      "type": "string",
      "example": "HTTP_BAD_REQUEST",
      "description": "Stable machine-readable domain code, or an HTTP_* fallback when no domain code is provided. Branch on this field and the HTTP status; localized wording never controls retries or business decisions."
    },
    "message": {
      "type": "string",
      "example": "errors:http.badRequest",
      "description": "Translation key, identical to translationKey. The API does not return localized display text. Resolve the key and translationValues in the consuming application."
    },
    "translationKey": {
      "type": "string",
      "example": "errors:http.badRequest",
      "description": "Canonical translation key, identical to message. Status-specific errors:http.* keys cover unspecified failures. Public keys and EN/RU explanations are listed in Developers; unknown keys require a localized client fallback."
    },
    "translationValues": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "example": "example"
          },
          {
            "type": "number",
            "example": 0
          },
          {
            "type": "boolean",
            "example": true
          }
        ],
        "example": "example"
      },
      "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
      "example": {
        "exampleKey": "example"
      }
    },
    "validationErrors": {
      "description": "Field validation failures with translation keys and stable validator codes. Submitted values and raw validator text are not included.",
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/ValidationErrorDto"
      },
      "example": [
        {
          "field": "email",
          "translationKey": "validation:isEmail",
          "code": "isEmail",
          "message": "validation:isEmail"
        }
      ]
    },
    "details": {
      "description": "Optional domain-specific blocker or validation details",
      "oneOf": [
        {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/JsonValue"
          },
          "example": [
            "example"
          ]
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/components/schemas/JsonValue"
          },
          "example": {
            "exampleKey": "example"
          }
        }
      ],
      "example": [
        "example"
      ]
    }
  },
  "required": [
    "statusCode",
    "error",
    "code",
    "message",
    "translationKey"
  ],
  "description": "Stable error envelope emitted by the global HTTP exception boundary. Domain-specific machine data, when present, is nested under details.",
  "example": {
    "statusCode": 400,
    "error": "errors:http.badRequest",
    "code": "HTTP_BAD_REQUEST",
    "message": "errors:http.badRequest",
    "translationKey": "errors:http.badRequest"
  }
}
ValidationErrorDto

Field validation failure with a field path, stable validator code and a translation key. Human-readable text belongs to the consuming application.

fieldRequired

Public field path. Nested properties and array indices are separated by dots.

string
Full definition
{
  "type": "string",
  "example": "email",
  "description": "Public field path. Nested properties and array indices are separated by dots."
}
translationKeyRequired

Translation key for this validator, identical to message. Resolve it using a client dictionary; see the public Developers error catalog.

string
Full definition
{
  "type": "string",
  "example": "validation:isEmail",
  "description": "Translation key for this validator, identical to message. Resolve it using a client dictionary; see the public Developers error catalog."
}
codeRequired

Stable validator identifier for this field failure. Custom validators may define additional identifiers.

string
Full definition
{
  "type": "string",
  "example": "isEmail",
  "description": "Stable validator identifier for this field failure. Custom validators may define additional identifiers."
}
messageRequired

Translation key describing this field validation failure, identical to translationKey. Submitted values and validator prose are not included.

string
Full definition
{
  "type": "string",
  "example": "validation:isEmail",
  "description": "Translation key describing this field validation failure, identical to translationKey. Submitted values and validator prose are not included."
}
translationValuesOptional

Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.

object
Full definition
{
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "type": "string",
        "example": "example"
      },
      {
        "type": "number",
        "example": 0
      },
      {
        "type": "boolean",
        "example": true
      }
    ],
    "example": "example"
  },
  "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
  "example": {
    "exampleKey": "example"
  }
}
Full definition
{
  "type": "object",
  "properties": {
    "field": {
      "type": "string",
      "example": "email",
      "description": "Public field path. Nested properties and array indices are separated by dots."
    },
    "translationKey": {
      "type": "string",
      "example": "validation:isEmail",
      "description": "Translation key for this validator, identical to message. Resolve it using a client dictionary; see the public Developers error catalog."
    },
    "code": {
      "type": "string",
      "example": "isEmail",
      "description": "Stable validator identifier for this field failure. Custom validators may define additional identifiers."
    },
    "message": {
      "type": "string",
      "example": "validation:isEmail",
      "description": "Translation key describing this field validation failure, identical to translationKey. Submitted values and validator prose are not included."
    },
    "translationValues": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "example": "example"
          },
          {
            "type": "number",
            "example": 0
          },
          {
            "type": "boolean",
            "example": true
          }
        ],
        "example": "example"
      },
      "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
      "example": {
        "exampleKey": "example"
      }
    }
  },
  "required": [
    "field",
    "translationKey",
    "code",
    "message"
  ],
  "description": "Field validation failure with a field path, stable validator code and a translation key. Human-readable text belongs to the consuming application.",
  "example": {
    "field": "email",
    "translationKey": "validation:isEmail",
    "code": "isEmail",
    "message": "validation:isEmail"
  }
}
JsonValue

Recursively JSON-safe value used only where the owning contract intentionally allows free-form structured data.

Full definition
{
  "oneOf": [
    {
      "type": "string",
      "nullable": true,
      "example": "example"
    },
    {
      "type": "number",
      "example": 0
    },
    {
      "type": "boolean",
      "example": true
    },
    {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": [
        "example"
      ]
    },
    {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": {
        "exampleKey": "example"
      }
    }
  ],
  "description": "Recursively JSON-safe value used only where the owning contract intentionally allows free-form structured data.",
  "example": "example"
}

Hallify uses essential cookies and optional analytics.

Essential cookies keep sign-in, locale, and theme preferences working. Analytics is off until you choose to allow it.