Based on your description, I would use option three. Option two is probably the worst of the bunch since you would be maximizing duplication and minimizing reuse.
Option one is the inheritance model. I don't feel like it's a good fit for the situation. The resulting class hierarchy will introduce complexity but you won't be gaining much in the trade-off. Inheritance can be very useful when you have a number of different objects which all share a common superclass. In this case you really only have one type of object (a car), you just have varying levels of completeness.
With your single car class from option three, there are some good tricks you can use like lazy loading of properties. Basically if your class has been filled with the least amount of data possible then in the getter of the other properties you can trigger a call out to the more detailed API and fill in the rest of the information. Be careful to model this type of behavior around actual usage patterns the object may see, but it can greatly help with ease of use for other programmers who consume your object.
I'd say it depends on your audience.
No-dev
If your audience is not a developer's one, I'd go with the following way:
Let's say you return JSON for the sake of the example.
GET /cats HTTP/1.1
{
"cats": [
"Can I haz cheeseburger",
"If it fits, I sits",
"It's caturday!"
],
"permissions": {
"level": "free",
"information": "You have access to 3 cats. Upgrade to ... to get 10 cats!"
}
}
Or something similar.
It is informative for the user to know what the status of his account is, and it allows you to put whatever information you want, such as a marketing message. The most important point of this way is to give some easy visibility to your users of their current account.
Dev
However, if your audience is purely developers, then I'd say: go with the full HTTP compliant way. To store the metadata, you use HTTP headers.
Here is an example:
GET /cats HTTP/1.1
X-Account: anonymous
X-Account-Possible-Upgrades: 2
X-Account-Limit: 3
Then, provide a clear documentation of what these headers mean. Most developers will go straight for the documentation when they'll see these custom headers, especially if they're seeing a limit. You can go even further and show the link in the headers. Or you can show a link to the pricing page.
X-Account-Doc: http://your/doc
But then again, many developers don't know how HTTP works.
So it's your call
One is more correct, the other is more accessible.
Misc
Some other miscellaneous stuff related to your question:
Best Answer
Separate your entities from your API response model. This is a case of SRP (Single Responsibility Principle): the job of your entities is to make DB access convenient. Your are adding two more responsibilities to that, violating the SRP:
That means that there are two parts to this answer.
having a public API
A public API must be stable and backwards compatible unless stated to your users in the most explicit way possible. That means any change in your codebase that changes the public API should be carefully checked for backwards compatibility before releasing it to production. With your current approach, you'll have a very hard time doing so: say you want to rename a property of your entity. Fine, you did so, your IDE caught all the usages and renamed them. But what about other code that uses your API? It will break because it is still looking for the old name. What you really want here is that you can change your entities and not affect the public API as long as all the information is still there. The solution: have separate classes for the API. For each Entity, have another class that (right now) mirrors the Entity. When receiving input from the API, convert the JSON into these intermediate instances. Do validation and stuff and only then cop data to your entities. When giving data out, first convert your entities to those intermediate classes and then convert those to JSON. Yes, that means more work. But it gives you flexibilities that you will 100% definitely need as soon as you have published your API. That work is now easier done than 30 features later.
enforcing permissions
You can now decide whether you want to include this responsibility in the API representation classes or whether you want it separately. You could also include this in the process of copying data from the entity to the representation class. It really depends on your codebase, team and preference. Just make sure that, wherever you place that code, the SRP is not violated.
performance
As has been said, you can go as far as to not even fetch fields from the DB that are not visible due to permissions. For regular fields the performance impact should be ignorable (except when we're talking about BLOB fields with several KB). But where this really matters is with related entities. If you can avoid three joins because they won't be used anyways, that's a definitive and huge speedup. See iipavlov's answer on that issue.