EventBridge events
Outbound notifications are published with EventBridgeClient.put_event() to the bus
EVENT_BUS_NAME (prod_workers in release, the environment name in dev). A non-zero
FailedEntryCount raises ConnectionError, which fails the task.
def put_event(self, event: EventBridgeEvent):
event_body = event.get_body()
result = self.client.put_events(Entries=[event_body])
if isinstance(result, dict) and result.get('FailedEntryCount', 1):
raise ConnectionError('Cannot put event to Event Bridge.')
Event catalog
| Event class | Source |
DetailType |
Emitted by | When |
|---|---|---|---|---|
|
|
the uppercased process name |
Au10tix ID-doc, Entrust ID-verification, personal-info and personal-background handle tasks |
the process completed with a terminal result |
|
|
|
personal-info (KYC) handle task |
every PII field matched |
|
|
|
personal-info (KYC) handle task |
one or more PII fields did not match (carries |
|
|
|
personal-info (KYC) handle task |
the CLEAR call failed — the platform may let the customer proceed without the check |
DetailType values for ProcessFinishedEvent are therefore VALIDATE_IDENTITY_DOCUMENT,
VALIDATE_PERSONAL_INFORMATION and DOWNLOAD_PERSONAL_BACKGROUND_REPORT.
|
|
Payload shapes
Every event is a put_events entry whose Detail is a JSON string and always includes
project_name (automatic-uw-tool). Consumers route on Source + DetailType.
ProcessFinishedEvent
{
'Source': 'pyb.underwriting.events',
'EventBusName': settings.EVENT_BUS_NAME,
'DetailType': process_name.upper(),
'Detail': json.dumps({
'project_name': settings.PROJECT_NAME,
'message': f'The process {process_name} is finished',
'supplier_key': task_input['supplier_key'],
'person_id': task_input['person_id'],
'result_s3_path': result_s3_path,
'status': TaskExecutionTable.PROCESSED_STATUS
})
}
{
"Source": "pyb.underwriting.events",
"EventBusName": "prod_workers",
"DetailType": "VALIDATE_IDENTITY_DOCUMENT",
"Detail": "{\"project_name\": \"automatic-uw-tool\", \"message\": \"The process validate_identity_document is finished\", \"supplier_key\": \"9b1c4d3e-6f2a-4b8c-9d0e-1f2a3b4c5d6e\", \"person_id\": \"44f2a1b0-7c3d-4e5f-8a9b-0c1d2e3f4a5b\", \"result_s3_path\": \"entrust/identity_document_validation/supplier_key=9b1c.../person_id=44f2.../2026-08-12T09:15:11.204812.json\", \"status\": \"processed\"}"
}
status is always the literal processed — the event is only emitted on success. The
result_s3_path points into the datalake (S3 datalake).
|
|
ThomsonReutersDataNotMatchEvent
{
'Source': 'pyb.internal.admin.events',
'EventBusName': settings.EVENT_BUS_NAME,
'DetailType': 'THOMSON_REUTERS_DATA_NOT_MATCH',
'Detail': json.dumps({
'project_name': settings.PROJECT_NAME,
'message': 'Customer data is not a match with Thomson Reuters. '
'Incorrect data points are {}'.format(data_points),
'task_input': task_input
})
}
data_points is the list of mismatched field names (both PARTIAL MATCH and NO MATCH count
as mismatched), rendered into message. The full task_input — including PII — travels inside
Detail.
ThomsonReutersDataMatchEvent and ThomsonReutersNotWorkingEvent
Same shape (Source: pyb.internal.admin.events, project_name, message, task_input),
differing only in DetailType and message text:
-
match —
"All customer data is match". -
not working —
"Due to error with Thomson Reuters, could not validate data. Allowing customer to proceed without data check."
Not on this bus: supplier events
The Entrust flow also emits supplier events to Payability’s internal EventLogger service — a separate, supplier-timeline channel, not EventBridge. It is best effort and carries the verification lifecycle status rather than a process completion. See Supplier event logger.
Consuming these events
Consumers live outside this repository. Subscribe an EventBridge rule on the bus for the
relevant Source and DetailType. The pyb.underwriting.events events are the primary
"a result is ready" signal; the pyb.internal.admin.events events drive internal KYC review and
notification flows.
Adding an event
-
Add a class under
components/event_bridge/events/extendingEventBridgeEventwith a stableSourceandDetailType. -
Emit it from the relevant handle task through the injected
event_bridge_client. -
Keep it idempotent-friendly: a replayed activity will re-emit it, so consumers must tolerate duplicates.
-
Document it in the catalog above.