Apply Coupon Validation in Order
IsAppliedCouponValid()


Don't omit braces although they might be optional. Omitting braces can lead to hidden and therfor hard to find bugs.  
The intermediate variables startDate and endDate won't buy you much. Instead I would just use the coupon.StartDate and coupon.EndDate. Don't get me wrong, using intermediate variables can be a good thing but not for such simple stuff.  
A construct like  

if (!bool)  
{
    return false;
}
return true;  


can be rewritten as return bool;  
You "validate"  the passed Coupon coupon but you don't validate string userID. The method parameters Order order, int? categoryID aren't used and should be removed.  
Sometimes you use if (bool == false) and sometimes you use if (!bool) where I prefer the first because it is easier to see that we check if the value is false. Whatever style you choose, you should stick to it. 
The check for the coupon regarding null and coupon.Status could be added in a condition using ||.  
Comments like //check date range or //check coupon applied limitations are superflous and unneeded comments because they tell the reader of the code what is done by the code. Telling what the code is doing should be done by the code itself by having meaningful names. The why something is done in the way it is done is where we need and want comments.


Applying these points will lead to  

public async Task&lt;bool&gt; IsAppliedCouponValid(Coupon coupon, string userID)
{
    if (userID==null) { throw new ArgumentNullException(nameof(userID)); }

    if (coupon == null || coupon.Status == false)
    {
        return false;
    }

    var now = DateTime.UtcNow;

    if (coupon.StartDate.CompareTo(now) &gt; 0)
    {
        return false;
    }

    if (coupon.EndDate.CompareTo(now) &lt; 0)
    {
        return false;
    }

    return await CheckCouponLimitations(coupon, userID);
}