You should put your objects in the body of a POST request instead of using the URL :
@RequestMapping(value = "generateBill/{id}", method = RequestMethod.POST)
public String generateBill(@PathVariable Long id, @RequestBody BillingRequest billingRequest) {
   // do things
}
Also, mapping directly a collection in the payload is not evolvable (you cannot add new "fields" outside the array), it's generally a good practice to wrap your array in a JSON object : 
public class BillingRequest {
    List<Rate> rates;
    // Here you could add other fields in the future
}
Your HTTP request to call your service would look like this :
POST / HTTP/1.1
{  
  "rates" : [
     {
       "version" : 1,
       "amount" : 33.3,
       "validFrom" : "2016-01-01",
       "validUntil" : "2017-01-01" 
     },
     {
       "version" : 2,
       "amount" : 10.0,
       "validFrom" : "2016-02-01",
       "validUntil" : "2016-10-01" 
     }
   ] 
}
One last piece of advice about your model :
- Use 
java.time.LocalDate (or jodatime) instead of java.util.Date. If you need date+time, use java.time.ZonedDateTime (DateTime if you use jodatime) 
- Use 
java.math.BigDecimal to represent exact numbers. Floating point numbers like Double can lose precision 
EDIT : I would suggest using Instant rather than ZonedDateTime, which is a timestamp with UTC timezone. Unless of course your domain requires different timezones.