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:
- Configuration: Define which event types to subscribe to (routes) and where to send them (providers).
- Event Generation: When a matching operation occurs, IndyKite generates a message conforming to the CloudEvents standard.
- 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:
- Perform an operation that matches your route (e.g., capture a node).
- Check your provider (Kafka topic, Azure Event Grid, Azure Service Bus) for the event message.
- Verify the message conforms to the CloudEvents standard.

Next Steps
- Terraform examples: Terraform Configurations
- REST API reference: Event Sink API
- Full examples: Developer Hub Resources