---
title: Native job observations and capture
description: Inspect Loops and Iterable operations through their own minimal or private instrumentation boundaries.
---

Use native instrumentation for `LoopsTransactionalEmail` and `IterableCampaignEmail`. Common sender-call wrappers do not describe these specialized service operations.

## Minimal operation facts

```ts
import { Effect, Redacted } from "effect";
import {
  EmailNativeObservations,
  observedLoopsTransactionalLayer,
} from "@corven/email-sdk/native-observations";
import type {
  EmailNativeObserver,
  EmailNativeStartingObserver,
} from "@corven/email-sdk/native-observations";
import { LoopsTransactionalEmail, loopsTransactionalLayer } from "@corven/email-sdk/loops";

export const observedNativeLoopsLayer = (
  observer: EmailNativeObserver,
  startingObserver?: EmailNativeStartingObserver,
) =>
  observedLoopsTransactionalLayer(
    loopsTransactionalLayer({
      apiKey: Redacted.make("fictional-unused-key"),
      attachments: "Disabled",
      templateAuthority: "ProviderManaged",
    }),
    { capacity: 100 },
    observer,
    startingObserver,
  );

export const inspectNativeOperationFacts = Effect.gen(function* inspectNativeOperationFacts() {
  const loops = yield* LoopsTransactionalEmail;
  const view = yield* EmailNativeObservations;

  const preview = yield* loops.validate({
    email: "recipient@fictional.invalid",
    transactionalId: "fictional-template",
  });

  return { observations: yield* view.snapshot, preview };
});
```

`observedLoopsTransactionalLayer` supplies `EmailNativeObservations`; the Iterable counterpart wraps campaign operations. A snapshot retains bounded `Receipt`, `Rejected` and `Unknown` facts with the native operation kind. The example validates a job; local validation alone is not a submitted-operation observation.

## Authorized private capture

```ts
import { Effect, Redacted, Schema } from "effect";
import {
  EmailNativeCapture,
  EmailNativeCapturePayloadSchema,
  capturedLoopsTransactionalLayer,
} from "@corven/email-sdk/native-capture";
import { LoopsTransactionalEmail, loopsTransactionalLayer } from "@corven/email-sdk/loops";

export const capturedNativeLoopsLayer = capturedLoopsTransactionalLayer(
  loopsTransactionalLayer({
    apiKey: Redacted.make("fictional-unused-key"),
    attachments: "Disabled",
    templateAuthority: "ProviderManaged",
  }),
  { capacity: 100, maxBytes: 8_388_608, privateData: "AuthorizePayloadCapture" },
);

export const inspectPrivateNativeCapture = Effect.gen(function* inspectPrivateNativeCapture() {
  const loops = yield* LoopsTransactionalEmail;
  yield* loops.validate({
    email: "recipient@fictional.invalid",
    transactionalId: "fictional-template",
  });
  const capture = yield* EmailNativeCapture;
  const snapshot = yield* capture.snapshot;

  const payloads = yield* Effect.forEach((payload: string) =>
    Schema.decodeEffect(Schema.fromJsonString(EmailNativeCapturePayloadSchema))(payload),
  )(snapshot.records.map((record) => Redacted.value(record.payloadJson)));

  const purgedRecordCount = yield* capture.purgeRecords;

  return { payloads, purgedRecordCount, snapshot };
});
```

`capturedLoopsTransactionalLayer` and `capturedIterableCampaignLayer` require count/byte bounds and `AuthorizePayloadCapture`. `EmailNativeCapture` exposes a Redacted payload view plus `purgeRecords`. Decode with `EmailNativeCapturePayloadSchema` only in an authorized private path.

Provide the configured HTTP transport before running these programs. Keep views and sending in the same acquisition. Callback failure cannot undo acknowledgment, truncation does not prove non-submission, and purging is not secure erasure of escaped data or permission to repeat a job.
