# `DripDrop`
[🔗](https://github.com/agoodway/dripdrop/blob/v0.2.1/lib/dripdrop.ex#L1)

Public entry point for DripDrop.

DripDrop is a backend-first, database-driven messaging sequence engine. The
foundation currently exposes boot-time validation while the domain APIs are
implemented capability by capability.

# `activate_sequence_version`

```elixir
@spec activate_sequence_version(Ecto.UUID.t()) ::
  {:ok, Ecto.Schema.t()} | {:error, term()}
```

Activates a sequence version and archives the previously active version.

# `add_pool_member`

```elixir
@spec add_pool_member(Ecto.Schema.t() | Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Adds an adapter to an outbound pool.

# `create_adapter_pool`

```elixir
@spec create_adapter_pool(map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates an outbound adapter pool.

# `create_channel_adapter`

```elixir
@spec create_channel_adapter(map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates a channel adapter.

# `create_condition`

```elixir
@spec create_condition(Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates a condition attached to a step by default, or to a transition when `transition_id` is provided.

# `create_http_hook`

```elixir
@spec create_http_hook(Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates an HTTP hook for a sequence.

# `create_sequence`

```elixir
@spec create_sequence(map()) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates a sequence.

# `create_sequence_version`

```elixir
@spec create_sequence_version(Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates a sequence version.

# `create_step`

```elixir
@spec create_step(Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates a step in a sequence version.

# `create_step_transition`

```elixir
@spec create_step_transition(Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates a transition in a sequence version.

# `delete_adapter_pool`

```elixir
@spec delete_adapter_pool(Ecto.Schema.t() | Ecto.UUID.t(), map() | keyword()) ::
  {:ok, Ecto.Schema.t()} | {:error, map()}
```

Deletes an outbound adapter pool.

# `enroll`

```elixir
@spec enroll(map()) :: {:ok, Ecto.Schema.t()} | {:error, term()}
```

Enrolls a subscriber into the active version of a sequence.

# `get_active_sequence_version`

```elixir
@spec get_active_sequence_version(Ecto.UUID.t()) :: Ecto.Schema.t() | nil
```

Gets a sequence's currently active version, or `nil` when none is active.

# `get_active_sequence_version!`

```elixir
@spec get_active_sequence_version!(Ecto.UUID.t()) :: Ecto.Schema.t()
```

Gets a sequence's currently active version, raising when none is active.

# `get_default_adapter`

```elixir
@spec get_default_adapter(binary() | atom(), binary() | nil) :: Ecto.Schema.t() | nil
```

Gets the active default adapter for a channel and tenant, falling back to the global default.

# `get_enrollment`

```elixir
@spec get_enrollment(Ecto.UUID.t(), binary(), binary()) :: no_return()
```

Deprecated unscoped enrollment lookup. Use `get_enrollment/4`.

# `get_enrollment`

```elixir
@spec get_enrollment(Ecto.UUID.t(), binary(), binary(), binary() | nil) ::
  Ecto.Schema.t() | nil
```

Gets an enrollment by sequence, subscriber identity, and explicit tenant scope.

# `get_global_channel_adapter`

```elixir
@spec get_global_channel_adapter(binary(), binary()) :: Ecto.Schema.t() | nil
```

Gets the global (tenant-less) channel adapter for a channel and provider.

# `get_sequence`

```elixir
@spec get_sequence(binary() | nil, String.t()) :: Ecto.Schema.t() | nil
```

Fetches a sequence by `key` within a tenant scope.

Pass `nil` for `tenant_key` to look up a global (tenant-less) sequence.

# `ingest_inbound_message`

```elixir
@spec ingest_inbound_message(Ecto.UUID.t() | map(), map()) :: :ok | {:error, term()}
```

Ingests a normalized inbound email from host-owned inbox infrastructure.

Example:

    DripDrop.ingest_inbound_message(adapter.id, %{
      message_id: "reply@gmail.com",
      in_reply_to: "0197...@example.com",
      references: ["0197...@example.com"],
      from: "prospect@example.org",
      to: "sales@example.com",
      body_text: "Sure, let's talk.",
      received_at: DateTime.utc_now(),
      intent: :reply
    })

Hosts can feed this from IMAP, Gmail API watches, or Microsoft Graph
subscriptions after normalizing provider-specific payloads into this map.

# `latest_step_by_key`

```elixir
@spec latest_step_by_key(Ecto.UUID.t(), String.t()) :: Ecto.Schema.t() | nil
```

Gets the most recently authored step for a `key` across all of a sequence's versions.

# `list_active_enrollments`

```elixir
@spec list_active_enrollments(map()) :: [Ecto.Schema.t()]
```

Lists active enrollments.

# `list_adapter_pools`

```elixir
@spec list_adapter_pools(map()) :: [Ecto.Schema.t()]
```

Lists outbound adapter pools.

# `list_channel_adapters`

```elixir
@spec list_channel_adapters(map()) :: [Ecto.Schema.t()]
```

Lists channel adapters.

# `list_http_hooks`

```elixir
@spec list_http_hooks(Ecto.UUID.t()) :: no_return()
```

Deprecated unscoped HTTP hook listing. Use `list_http_hooks/2`.

# `list_http_hooks`

```elixir
@spec list_http_hooks(Ecto.UUID.t(), binary() | nil) :: [Ecto.Schema.t()]
```

Lists HTTP hooks for a sequence and explicit tenant scope.

# `list_pool_members`

```elixir
@spec list_pool_members(Ecto.Schema.t() | Ecto.UUID.t() | map()) :: [Ecto.Schema.t()]
```

Lists outbound pool members.

# `max_version_number`

```elixir
@spec max_version_number(Ecto.UUID.t()) :: non_neg_integer()
```

Returns the highest authored version number for a sequence, or `0` when it has none.

# `ordered_steps`

```elixir
@spec ordered_steps(Ecto.UUID.t()) :: [Ecto.Schema.t()]
```

Lists a sequence version's steps, ordered by their position.

# `pause_enrollment`

```elixir
@spec pause_enrollment(Ecto.UUID.t()) :: no_return()
```

Deprecated unscoped pause. Use `pause_enrollment/2`.

# `pause_enrollment`

```elixir
@spec pause_enrollment(Ecto.UUID.t(), binary() | nil) ::
  {:ok, Ecto.Schema.t()} | {:error, term()}
```

Pauses an enrollment scoped by tenant.

# `remove_pool_member`

```elixir
@spec remove_pool_member(Ecto.Schema.t() | Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, :not_found}
```

Removes an adapter from an outbound pool.

# `repin_enrollment`

```elixir
@spec repin_enrollment(Ecto.UUID.t(), Ecto.UUID.t(), keyword() | map()) ::
  {:ok, Ecto.Schema.t()} | {:error, term()}
```

Reassigns an enrollment to a different outbound adapter.

# `replay`

```elixir
@spec replay(Ecto.UUID.t()) :: {:ok, Ecto.Schema.t()} | {:error, term()}
```

Replays a failed step execution with a fresh idempotency key.

# `resume_enrollment`

```elixir
@spec resume_enrollment(Ecto.UUID.t()) :: no_return()
```

Deprecated unscoped resume. Use `resume_enrollment/2`.

# `resume_enrollment`

```elixir
@spec resume_enrollment(Ecto.UUID.t(), binary() | nil) ::
  {:ok, Ecto.Schema.t()} | {:error, term()}
```

Resumes an enrollment scoped by tenant.

# `set_adapter_health`

```elixir
@spec set_adapter_health(Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, term()}
```

Sets an adapter health state from a host-supplied external signal.

# `set_adapter_sequence_budget`

```elixir
@spec set_adapter_sequence_budget(Ecto.UUID.t(), Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates or updates an outbound adapter sequence budget.

# `startup_check`

```elixir
@spec startup_check() :: :ok | {:error, [DripDrop.StartupCheck.error()]}
```

Validates the host application's DripDrop runtime configuration.

This check is intended for host `Application.start/2` callbacks after the
host Repo, PgFlow supervisor, and custom channel registrations have been
configured.

# `steps_by_key`

```elixir
@spec steps_by_key(Ecto.UUID.t()) :: %{required(String.t()) =&gt; Ecto.Schema.t()}
```

Maps a sequence version's steps by their `key`.

# `suppress`

```elixir
@spec suppress(map()) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Creates or updates a suppression for a channel recipient.

# `test_http_hook`

```elixir
@spec test_http_hook(Ecto.UUID.t(), map()) :: {:ok, term()} | {:error, term()}
```

Runs an HTTP hook out of band and stores its redacted test result.

# `track_event`

```elixir
@spec track_event(Ecto.UUID.t() | map(), binary(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()} | no_return()
```

Tracks an event by subscriber identity (tenant_key in the map) or deprecated unscoped enrollment id.

# `track_event`

```elixir
@spec track_event(Ecto.UUID.t(), binary(), map(), binary() | nil) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Tracks an event for a tenant-scoped enrollment id.

# `unenroll`

```elixir
@spec unenroll(Ecto.UUID.t()) :: no_return()
```

Deprecated unscoped cancel. Use `unenroll/2`.

# `unenroll`

```elixir
@spec unenroll(Ecto.UUID.t(), binary() | nil) ::
  {:ok, Ecto.Schema.t()} | {:error, term()}
```

Cancels an enrollment scoped by tenant.

# `update_adapter_pool`

```elixir
@spec update_adapter_pool(Ecto.Schema.t() | Ecto.UUID.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Updates an outbound adapter pool.

# `update_channel_adapter`

```elixir
@spec update_channel_adapter(Ecto.Schema.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Updates a channel adapter.

# `update_http_hook`

```elixir
@spec update_http_hook(Ecto.Schema.t(), map()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
```

Updates an HTTP hook.

# `validate_sequence_version`

```elixir
@spec validate_sequence_version(Ecto.UUID.t()) ::
  {:ok, Ecto.Schema.t()} | {:error, list()}
```

Validates a sequence version before activation.

# `webhook_routes`

```elixir
@spec webhook_routes() :: [DripDrop.Channel.webhook_route()]
```

Returns webhook routes declared by active channel adapters.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
