Backend interface VS hard contract Here is an API for using a warehouse:

public static class WarehouseClient
{
    event Action&lt;IWarehouse&gt; WarehouseCreated;
}

public interface IWarehouse
{
    event Action&lt;IWarehouseSession&gt; NextSession;

    IWarehouseSession Session { get; }

    WarehouseInfo Info { get; }
}

public interface IWarehouseSession
{
    event Action Opened;

    event Action Closed;

    bool IsOpen { get; }

    TariffPolicy TariffPolicy { get; }

    IEnumerable&lt;ITerminal&gt; Terminals { get; }
}

public interface ITerminal
{
    event Action&lt;double&gt; FreeSpaceUpdated;

    string TerminalLetter { get; }

    double FreeSpace { get; }

    IDeposit Deposit(object item);
}

public interface IDeposit
{
    object Item { get; }

    event Action ItemAccepted;

    event Action&lt;int&gt; ItemDeposited;

    event Action ItemWithdrawn;

    void Withdraw();
}


(WarehouseInfo and TariffPolicy are immutable value-like classes)

Also I've got third-party connections to warehouses with interfaces adaptable to mine. But I doubt if I need a mirrored API for connection wrappers, like:

public static class WarehouseProvider
{
    IWarehouseBackend CreateWarehouse(WarehouseInfo info);
}

public interface IWarehouseBackend
{
    IWarehouseSessionBackend Session { get; }

    WarehouseInfo Info { get; }

    IWarehouseSessionBackend NextSession(TariffPolicy tp, params string[] terminalLetters);
}

public interface IWarehouseSessionBackend
{
    bool IsOpen { get; }

    TariffPolicy TariffPolicy { get; }

    IEnumerable&lt;ITerminalBackend&gt; Terminals { get; }

    void Open();

    void Close();
}

public interface ITerminalBackend
{
    // ... and so on


This backend-api can be implemented by library's internal classes.

Removing it means much less code (though it almost written) and harder-to-implement contract for warehouse providers.

So, my question is: do I need backend api?

Also, I would be very grateful for reviewing this API.
You definitely want to document those interfaces.
WarehouseClient should probably not be a static class.
The name of the NextSession event in IWarehouse doesn't really mean anything to me. Just from reading the interface I don't really know when this event would be raised. Maybe NextSessionCreated or NextSessionOpened?
CurrentSession would be a better name instead of Session.
Also it is not clear if the Session can get opened and closed multiple times. If a session can't be opened and closed multiple time then maybe use Start and Finalize instead? Those imply (at least to me) more of a once only action.
In IDeposit: ItemWithdrawed should be ItemWithdrawn
I'm not 100% sure about the ITerminal and IDeposit relation. The way I read is that a client can deposit an object into a terminal which will then give him some kind of reference to that transaction in form of an IDeposit. Now IDeposit also has a Withdraw() method but it's not clear what the semantics of that is. Can the client who deposited the item basically withdraw that deposit? Or is it mean to be withdrawn by someone else - if yes then shouldn't there be a Withdraw() method on the terminal rather than on the deposit? It's probably not clear to me because I don't know what the workflow is supposed to be but it's hard to deduce from just the interfaces alone.


All that being said I'd say: Yes you want that backend API. Apparently the whole system expects a certain kind of workflow and providing a structure which an implementer can fill in will make it much easier for them and probably reduce bugs.