Skip to content
Sections

Workforce events

Accept a signed, replay-safe workforce provider event

POST/organizations/{organizationId}/workforce/integrations/{connectionId}/webhooks

Accepts a workforce provider event only after profile-specific HMAC verification over stable JSON, timestamp freshness, and replay checks. Event identity and payload hash make duplicate delivery deterministic. New imports and bidirectional exchanges require current commercial coverage; exact replays and export-only exchanges retain their recovery paths. Hallify HMAC profile workforce-integration uses HMAC-SHA256. Canonical input: RFC3339 timestamp + "." + recursively key-sorted stable JSON. Send x-hallify-timestamp as rfc3339; timestamps outside ±300 seconds are stale. Send x-hallify-signature as lowercase hexadecimal with optional sha256= prefix; comparison is timing-safe. Secret handling: Use the integration secret as UTF-8 text. Accepted Content-Type: application/json. Malformed input: A malformed signature returns 401 WORKFORCE_INTEGRATION_WEBHOOK_INVALID. Stale input: A timestamp outside the 300-second window returns 401 WORKFORCE_INTEGRATION_WEBHOOK_INVALID. Repeated delivery: The external event ID and payload hash provide duplicate handling; a conflicting replay returns 409 WORKFORCE_INTEGRATION_WEBHOOK_REPLAY_CONFLICT. Every delivery still requires current HMAC verification and an available scoped connection. Exact signed replays return the saved result without fresh commercial coverage. New IMPORT or BIDIRECTIONAL events require current organization coverage and may return 402; EXPORT-only events do not require fresh coverage. These commercial exemptions do not bypass security prerequisites.

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"
}
connectionIdPath · Required

Hallify UUID whose ownership is validated against every parent tenant and aggregate in this route before the selected resource is exposed or changed.

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

rfc3339 timestamp; accepted clock skew is ±300 seconds.

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

Request body

Required

External event identifier, provider event type, and free-form provider payload consumed together as the signed, replay-deduplicated workforce event.

application/json

WorkforceIntegrationWebhookDto
Full definition
{
  "$ref": "#/components/schemas/WorkforceIntegrationWebhookDto"
}

Responses

200Accepts a workforce provider event only after profile-specific HMAC verification over stable JSON, timestamp freshness, and replay checks.
WorkforceIntegrationWebhookResultDto
Full definition
{
  "$ref": "#/components/schemas/WorkforceIntegrationWebhookResultDto"
}
Example response · 200 · application/json
{
  "eventId": "84a46351-8af3-4a2c-8698-e4a6a5cafb2b",
  "accepted": true,
  "duplicate": true
}
400Integration identifiers or webhook payload are invalid
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"
}
401Workforce webhook HMAC signature is invalid or stale
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"
}
402Commercial coverage is required for new demand, or this operation has no original commercial admission evidence. Existing authorized reads and financial recovery remain available. Commercial coverage is required for a new IMPORT or BIDIRECTIONAL event. Exact signed replays and EXPORT-only events retain their recovery paths without fresh coverage.
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 402 · application/json
{
  "statusCode": 402,
  "error": "errors:http.failure",
  "code": "HTTP_402",
  "message": "errors:http.failure",
  "translationKey": "errors:http.failure"
}
404Workforce integration is unavailable or 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"
}
409External event identity was reused with a different payload, or verified integration configuration changed before admission
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"
}
413Workforce integration webhook payload is too large
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 413 · application/json
{
  "statusCode": 413,
  "error": "errors:http.payloadTooLarge",
  "code": "HTTP_PAYLOAD_TOO_LARGE",
  "message": "errors:http.payloadTooLarge",
  "translationKey": "errors:http.payloadTooLarge"
}
429Workforce integration webhook rate limit was exceeded

Response headers

Retry-After

Whole seconds the client must wait before retrying the rejected request.

integer
Full definition
{
  "type": "integer",
  "minimum": 1,
  "example": 60
}
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 429 · application/json
{
  "statusCode": 429,
  "error": "errors:http.tooManyRequests",
  "code": "HTTP_TOO_MANY_REQUESTS",
  "message": "errors:http.tooManyRequests",
  "translationKey": "errors:http.tooManyRequests"
}
503Authoritative commercial state is unavailable or cannot be read within its bounded source contract. Retry the same operation after recovery. Protected workforce integration configuration or authoritative commercial source is unavailable
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

WorkforceIntegrationWebhookDto

Accepts a workforce provider event only after profile-specific HMAC verification over stable JSON, timestamp freshness, and replay checks.

externalEventIdRequired

Opaque identifier for external event associated with workforce integration webhook; clients must not assume UUID syntax. Accepted values enforce maximum length 191.

string
Full definition
{
  "type": "string",
  "maxLength": 191,
  "description": "Opaque identifier for external event associated with workforce integration webhook; clients must not assume UUID syntax. Accepted values enforce maximum length 191.",
  "example": "example-id"
}
eventTypeRequired

Event type for workforce integration webhook. Accepted values enforce maximum length 160.

string
Full definition
{
  "type": "string",
  "maxLength": 160,
  "description": "Event type for workforce integration webhook. Accepted values enforce maximum length 160.",
  "example": "1.000"
}
payloadRequired

Structured event or provider payload carried by workforce integration webhook.

object
Full definition
{
  "type": "object",
  "additionalProperties": {
    "$ref": "#/components/schemas/JsonValue"
  },
  "description": "Structured event or provider payload carried by workforce integration webhook.",
  "example": {
    "exampleKey": "example"
  }
}
Full definition
{
  "type": "object",
  "properties": {
    "externalEventId": {
      "type": "string",
      "maxLength": 191,
      "description": "Opaque identifier for external event associated with workforce integration webhook; clients must not assume UUID syntax. Accepted values enforce maximum length 191.",
      "example": "example-id"
    },
    "eventType": {
      "type": "string",
      "maxLength": 160,
      "description": "Event type for workforce integration webhook. Accepted values enforce maximum length 160.",
      "example": "1.000"
    },
    "payload": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "description": "Structured event or provider payload carried by workforce integration webhook.",
      "example": {
        "exampleKey": "example"
      }
    }
  },
  "required": [
    "externalEventId",
    "eventType",
    "payload"
  ],
  "description": "Accepts a workforce provider event only after profile-specific HMAC verification over stable JSON, timestamp freshness, and replay checks.",
  "example": {
    "externalEventId": "example-id",
    "eventType": "1.000",
    "payload": {
      "exampleKey": "example"
    }
  }
}
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"
}
WorkforceIntegrationWebhookResultDto

Accepts a workforce provider event only after profile-specific HMAC verification over stable JSON, timestamp freshness, and replay checks.

eventIdRequired

Hallify UUID identifying event associated with workforce integration webhook.

string · uuid
Full definition
{
  "type": "string",
  "format": "uuid",
  "description": "Hallify UUID identifying event associated with workforce integration webhook.",
  "example": "84a46351-8af3-4a2c-8698-e4a6a5cafb2b"
}
acceptedRequired

Whether the submitted operation was accepted for processing.

boolean
Full definition
{
  "type": "boolean",
  "description": "Whether the submitted operation was accepted for processing.",
  "example": true
}
duplicateRequired

Whether the submitted event was already accepted and handled as a duplicate.

boolean
Full definition
{
  "type": "boolean",
  "description": "Whether the submitted event was already accepted and handled as a duplicate.",
  "example": true
}
Full definition
{
  "type": "object",
  "properties": {
    "eventId": {
      "type": "string",
      "format": "uuid",
      "description": "Hallify UUID identifying event associated with workforce integration webhook.",
      "example": "84a46351-8af3-4a2c-8698-e4a6a5cafb2b"
    },
    "accepted": {
      "type": "boolean",
      "description": "Whether the submitted operation was accepted for processing.",
      "example": true
    },
    "duplicate": {
      "type": "boolean",
      "description": "Whether the submitted event was already accepted and handled as a duplicate.",
      "example": true
    }
  },
  "required": [
    "eventId",
    "accepted",
    "duplicate"
  ],
  "description": "Accepts a workforce provider event only after profile-specific HMAC verification over stable JSON, timestamp freshness, and replay checks.",
  "example": {
    "eventId": "84a46351-8af3-4a2c-8698-e4a6a5cafb2b",
    "accepted": true,
    "duplicate": 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"
  }
}

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.