```python
def run_reservoir(capacity: int, start: int, ticks: list) -> dict:
    """
    Simulate an irrigation reservoir tick by tick.

    Parameters:
    - capacity: An integer representing the maximum capacity of the reservoir.
    - start: An integer representing the initial level of the reservoir.
    - ticks: A list of tuples, where each tuple contains an inflow and a demand.

    Returns:
    A dictionary containing the ending level, total water spilled, total unmet demand,
    and total water actually drawn, in the structure {level, spilled, shortfall, served}.
    """

    # Validate inputs
    if not isinstance(capacity, int) or capacity <= 0:
        raise ValueError("Capacity must be a positive integer.")
    if not isinstance(start, int) or start < 0 or start > capacity:
        raise ValueError("Starting level must be an integer between 0 and the capacity.")
    if not isinstance(ticks, list) or not all(isinstance(tick, tuple) and len(tick) == 2 for tick in ticks):
        raise ValueError("Ticks must be a list of two-item tuples.")
    if not all(isinstance(inflow, int) and isinstance(demand, int) and inflow >= 0 and demand >= 0 for inflow, demand in ticks):
        raise ValueError("Inflow and demand must be non-negative integers.")

    # Initialize variables
    level = start
    spilled = 0
    shortfall = 0
    served = 0

    # Process each tick
    for inflow, demand in ticks:
        # Add inflow to the level
        level += inflow
        # Check if the level exceeds the capacity
        if level > capacity:
            spilled += level - capacity
            level = capacity
        # Draw demand from the level
        if demand <= level:
            served += demand
            level -= demand
        else:
            shortfall += demand - level
            level = 0

    # Return the results
    return {
        "level": level,
        "spilled": spilled,
        "shortfall": shortfall,
        "served": served
    }
```