Skip to content

Declarative captures

Declarative captures use fluent C# builder APIs to define CDC behavior in code.

  • Implement ICapturer
  • Configure the capture in Define(ICaptureBuilder builder)
public class InvoiceCapture : ICapturer
{
public void Define(ICaptureBuilder builder) => builder
.FromApi("InvoicingApi", _ => _
.OnRoute("/invoices")
.PollEvery("10m"))
.Key("id")
.Append<InvoiceStatusChanged>(_ => _
.WhenPropertyChanges("status")
.Set(e => e.Status, "$.status")
.Set(e => e.ChangedAt, "$context.occurred"));
}
  • FromApi(api, configure?)
  • FromWebhook(path, configure?)
  • FromMessageTopic(topic)

API source options:

  • OnRoute(route)
  • PollEvery(interval)

FromApi(api, ...) references a configured External Service by name. The External Service holds the base URL and authentication, so no authentication is configured on the API source. If no route is configured, the External Service base URL is used directly.

Webhook source options (webhook sources are inbound and configure their own authentication):

  • WithBasicAuth(username, password)
  • WithBearerToken(token)
  • WithOAuth(authority, clientId, clientSecret)

Authentication is never part of the capture declaration text, so that secrets and tokens do not live in capture definitions.

Use Key(propertyPath) to define the identity property used when comparing current vs. previous payload.

Use Map(...) on root, nested, or children scopes:

  • Rename(source, target)
  • Template(target, template)
  • Translate(target, source, entries => ...)
  • Split(source, separator, targets...)

Use Append<TEvent>(...) with one condition and one or more field assignments:

Condition methods:

  • WhenPropertyChanges(property)
  • WhenAnyOf(properties...)
  • WhenAllOf(properties...)
  • WhenTransition(property, from, to)
  • WhenAdded()
  • WhenRemoved()
  • WhenExpression(expression)

Assignment method:

  • Set(targetPropertyExpression, sourceExpression)
  • Nested(objectPath, configure) for nested object rules
  • Children(collectionPath, identifiedBy, configure) for child collection rules

Both support local Map(...) and Append<TEvent>(...) blocks.

You can set an explicit capture ID using [Capture("guid")] on the ICapturer type.