Entities
The base entity type and how domain objects are structured in Relay.
Every domain object in Relay -- event types, endpoints, events, deliveries, DLQ entries -- embeds a common base type that provides creation and update timestamps.
The base entity
The internal/entity package defines Entity:
type Entity struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}Create a new entity with entity.New(), which sets both timestamps to the current UTC time. IDs are assigned separately using the id package.
Domain entities
EventType
Defined in catalog/event_type.go. Wraps a WebhookDefinition with identity and state:
type EventType struct {
entity.Entity
ID id.ID `json:"id"`
Definition WebhookDefinition `json:"definition"`
IsDeprecated bool `json:"deprecated"`
DeprecatedAt *time.Time `json:"deprecated_at,omitempty"`
ScopeAppID string `json:"scope_app_id,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}Endpoint
Defined in endpoint/endpoint.go. A webhook delivery target registered by a tenant:
type Endpoint struct {
entity.Entity
ID id.ID `json:"id"`
TenantID string `json:"tenant_id"`
URL string `json:"url"`
Description string `json:"description"`
Secret string `json:"-"`
EventTypes []string `json:"event_types"`
Headers map[string]string `json:"headers,omitempty"`
Enabled bool `json:"enabled"`
RateLimit int `json:"rate_limit"`
Metadata map[string]string `json:"metadata,omitempty"`
}The Secret field is never serialized to JSON (tagged json:"-").
Event
Defined in event/event.go. A webhook event submitted for delivery:
type Event struct {
entity.Entity
ID id.ID `json:"id"`
Type string `json:"type"`
TenantID string `json:"tenant_id"`
Data any `json:"data"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
}Delivery
Defined in delivery/delivery.go. A single webhook delivery attempt:
type Delivery struct {
entity.Entity
ID id.ID `json:"id"`
EventID id.ID `json:"event_id"`
EndpointID id.ID `json:"endpoint_id"`
State State `json:"state"`
AttemptCount int `json:"attempt_count"`
MaxAttempts int `json:"max_attempts"`
NextAttemptAt time.Time `json:"next_attempt_at"`
LastError string `json:"last_error,omitempty"`
LastStatusCode int `json:"last_status_code,omitempty"`
LastResponse string `json:"last_response,omitempty"`
LastLatencyMs int `json:"last_latency_ms,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
}Delivery states: pending, delivered, failed.
DLQ Entry
Defined in dlq/entry.go. A permanently failed delivery:
type Entry struct {
entity.Entity
ID id.ID `json:"id"`
DeliveryID id.ID `json:"delivery_id"`
EventID id.ID `json:"event_id"`
EndpointID id.ID `json:"endpoint_id"`
EventType string `json:"event_type"`
TenantID string `json:"tenant_id"`
URL string `json:"url"`
Payload any `json:"payload"`
Error string `json:"error"`
AttemptCount int `json:"attempt_count"`
LastStatusCode int `json:"last_status_code,omitempty"`
ReplayedAt *time.Time `json:"replayed_at,omitempty"`
FailedAt time.Time `json:"failed_at"`
}WebhookDefinition
The canonical description of a webhook event type, defined in catalog/definition.go:
type WebhookDefinition struct {
Name string `json:"name"`
Description string `json:"description"`
Group string `json:"group,omitempty"`
Schema json.RawMessage `json:"schema,omitempty"`
SchemaVersion string `json:"schema_version,omitempty"`
Version string `json:"version"`
Example json.RawMessage `json:"example,omitempty"`
}The Name follows dot-separated convention: "invoice.created", "deployment.completed".