Back to all guides
Outbound Events

Outbound Events / Signal guide

What is needed to configure Events for the IndyKite platform.

What are Outbound Events?

Outbound Events (Signals) are real-time notifications sent to external systems when changes occur in your IndyKite environment.

Use Outbound Events when you need to:

  • Synchronize data with external systems in real-time.
  • Trigger workflows when specific data changes occur.
  • Audit and log operations performed on your IKG.
  • React to authorization or CIQ query executions.

Important: Only one Outbound Events configuration can exist per Project.

How do Outbound Events work?

The event flow consists of three stages:

  1. Configuration: Define which event types to subscribe to (routes) and where to send them (providers).
  2. Event Generation: When a matching operation occurs, IndyKite generates a message conforming to the CloudEvents standard.
  3. Event Publishing: The event is delivered to the configured provider(s).

After events are published, you are responsible for implementing any additional business logic for filtering and processing.

What providers are supported?

IndyKite supports three event providers:

  • Kafka (Confluent Cloud or self-hosted)
  • Azure Event Grid
  • Azure Service Bus

You can configure multiple providers and route different event types to different destinations.

How do I configure routing?

An Outbound Events configuration has two main components:

  • Providers: The destinations where events will be sent (Kafka topic, Azure Event Grid, Azure Service Bus).
  • Routes: Rules that determine which events go to which providers.

How does route ordering work?

Routes are evaluated sequentially in order. An event can match multiple routes and be sent to multiple destinations.

  • If an event matches multiple routes, it is sent to all matching destinations.
  • Wildcard routes (e.g., indykite.audit.capture.*) catch all matching events.
  • Place specific routes before wildcard routes to ensure correct processing.

What does the stop_processing flag do?

The stop_processing flag controls whether to continue evaluating routes after a match:

  • stop_processing = true: Stop after this route matches. Event is not evaluated against further routes.
  • stop_processing = false (default): Continue matching. Event may be sent to multiple destinations.

What event types can I filter?

Capture Events (Data Operations)

Operation Event Type Filters Available
BatchUpsertNodes indykite.audit.capture.batch.upsert.node captureLabel, property key/value
BatchUpsertRelationships indykite.audit.capture.batch.upsert.relationship captureLabel, property key/value
BatchDeleteNodes indykite.audit.capture.batch.delete.node captureLabel, property key/value
BatchDeleteRelationships indykite.audit.capture.batch.delete.relationship captureLabel
BatchDeleteNodeProperties indykite.audit.capture.batch.delete.node.property
BatchDeleteRelationshipProperties indykite.audit.capture.delete.relationship.property
BatchDeleteNodeTags indykite.audit.capture.batch.delete.node.tag captureLabel
All Capture Events indykite.audit.capture.* Wildcard matches all

Configuration Events

Operation Event Type
Create configuration indykite.audit.config.create
Read configuration indykite.audit.config.read
Update configuration indykite.audit.config.update
Delete configuration indykite.audit.config.delete
Assign permission indykite.audit.config.permission.assign
Revoke permission indykite.audit.config.permission.revoke
All Config Events indykite.audit.config.*

Authorization and CIQ Events

Operation Event Type
Token Introspect indykite.audit.credentials.token.introspected
IsAuthorized indykite.audit.authorization.isauthorized
WhatAuthorized indykite.audit.authorization.whatauthorized
WhoAuthorized indykite.audit.authorization.whoauthorized
CIQ Execute indykite.audit.ciq.execute

How do I configure Outbound Events?

Example 1: Send all Capture events to Kafka

Goal: Send an event to a Kafka topic each time a node or relationship is captured (upsert or delete).

Using Terraform

Documentation: indykite_event_sink resource

resource "indykite_event_sink" "outbound_events" {
	name         = "outbound-events"
	display_name = "Outbound Events"
	location     = "gid:YOUR_PROJECT_GID"
providers {
	provider_name = "confluent-provider"
	kafka {
		brokers  = ["pkc-xxxxx.region.gcp.confluent.cloud:9092"]
		topic    = "topic_signal"
		username = "<your-api-key>"
		password = "<your-api-secret>"
	}
}

routes {
	provider_id        = "confluent-provider"
	route_id           = "capture-events"
	route_display_name = "Capture Events"
	stop_processing    = true
	keys_values_filter {
		event_type = "indykite.audit.capture.*"
	}
}

}

Using REST API

Endpoint: POST /event-sinks

{
	"project_id": "YOUR_PROJECT_GID",
	"name": "outbound-events",
	"display_name": "Outbound Events",
	"description": "Capture events to Kafka",
	"providers": {
		"confluent-provider": {
			"kafka": {
				"brokers": ["pkc-xxxxx.region.gcp.confluent.cloud:9092"],
				"topic": "topic_signal",
				"username": "",
				"password": "",
				"disable_tls": false,
				"tls_skip_verify": false
			}
		}
	},
	"routes": [
		{
			"provider_id": "confluent-provider",
			"route_id": "capture-events",
			"display_name": "Capture Events",
			"stop_processing": true,
			"event_type_key_values_filter": {
				"event_type": "indykite.audit.capture.*"
			}
		}
	]
}

Example 2: Filter events by node label and property

Goal: Send events only when a Person node with an email property is upserted.

Using Terraform

routes {
	provider_id        = "kafka-provider"
	route_id           = "person-email-events"
	route_display_name = "Person Email Events"
	stop_processing    = true
	keys_values_filter {
		event_type = "indykite.audit.capture.upsert.node"
		key_value_pairs {
			key   = "captureLabel"
			value = "Person"
		}
		key_value_pairs {
			key   = "email"
			value = "*"
		}
	}
}

Using REST API

{
	"provider_id": "kafka-provider",
	"route_id": "person-email-events",
	"display_name": "Person Email Events",
	"stop_processing": true,
	"event_type_key_values_filter": {
		"event_type": "indykite.audit.capture.upsert.node",
		"context_key_value": [
			{ "key": "captureLabel", "value": "Person" },
			{ "key": "email", "value": "*" }
		]
	}
}

Example 3: Route to multiple providers

Goal: Route different event types to different providers:

  • Person node captures → Kafka
  • CIQ executions → Azure Event Grid
  • Config changes → Azure Service Bus

Using Terraform

resource "indykite_event_sink" "multi_provider" {
	name         = "multi-provider-events"
	display_name = "Multi Provider Events"
	location     = "gid:YOUR_PROJECT_GID"
providers {
	provider_name = "kafka-provider"
	kafka {
		brokers  = ["broker1:9092", "broker2:9092"]
		topic    = "capture-events"
		username = "<your-api-key>"
		password = "<your-api-secret>"
	}
}

providers {
	provider_name = "azure-grid-provider"
	azure_event_grid {
		topic_endpoint = "https://your-topic.eventgrid.azure.net/api/events"
		access_key     = "<your-access-key>"
	}
}

providers {
	provider_name = "azure-bus-provider"
	azure_service_bus {
		connection_string   = "Endpoint=sb://your-namespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=<your-key>"
		queue_or_topic_name = "config-events"
	}
}

routes {
	provider_id        = "kafka-provider"
	route_id           = "person-captures"
	route_display_name = "Person Captures"
	stop_processing    = true
	keys_values_filter {
		event_type = "indykite.audit.capture.upsert.node"
		key_value_pairs {
			key   = "captureLabel"
			value = "Person"
		}
	}
}

routes {
	provider_id        = "azure-grid-provider"
	route_id           = "ciq-executions"
	route_display_name = "CIQ Executions"
	stop_processing    = true
	keys_values_filter {
		event_type = "indykite.audit.ciq.execute"
	}
}

routes {
	provider_id        = "azure-bus-provider"
	route_id           = "config-changes"
	route_display_name = "Config Changes"
	stop_processing    = true
	keys_values_filter {
		event_type = "indykite.audit.config.*"
	}
}

}

How do I filter by multiple labels?

To match nodes with multiple labels, add multiple captureLabel key-value pairs:

{
	"key": "captureLabel",
	"value": "Person"
},
{
	"key": "captureLabel",
	"value": "Human"
}

For this filter to match, the captured node must have:

  • "type": "Person"
  • "tags": ["Human"]

What are Kafka brokers?

A Kafka Broker is a server that receives, stores, and distributes messages between producers and consumers.

Why specify multiple brokers?

The primary reason is resilience. If the first broker is unavailable, the client tries the next one in the array.

Best practice: Include at least two brokers to ensure connectivity even if one broker is down.

"brokers": ["broker1.confluent.cloud:9092", "broker2.confluent.cloud:9092"]

How do TLS settings work?

What does disable_tls do?

Setting disable_tls = true connects to Kafka without encryption (plain TCP).

Setting TLS Enabled (default) TLS Disabled
Data encryption Encrypted in transit Unencrypted (vulnerable to interception)
Authentication Certificate-based verification None (unless using SASL)
Performance Slight overhead Slightly faster
Security Production-ready Development only

What does tls_skip_verify do?

Setting tls_skip_verify = true skips certificate validation while still encrypting data.

Setting Verify Enabled (default) Verify Skipped
Data encryption Encrypted Encrypted
Server authentication Certificate validated Certificate accepted without validation
MITM protection Protected Vulnerable
Use case Production Development with self-signed certs

Recommendation: Only disable TLS or skip verification in development environments or highly secure private networks.

Verification

After configuring Outbound Events:

  1. Perform an operation that matches your route (e.g., capture a node).
  2. Check your provider (Kafka topic, Azure Event Grid, Azure Service Bus) for the event message.
  3. Verify the message conforms to the CloudEvents standard.

Next Steps