BlogAPI design

One route. Two depths.

Use ?deep=true to request additional API response fields without moving existing fields. Learn when deep is omitted, empty, or populated.

An integration shouldn't need a rewrite when you decide you want more detail. If your app already reads the country and ASN from an IP lookup, those fields should stay where they are.

That is why extra detail lives in a nested deep object. You ask for it on the same route:

GET /ip/8.8.8.8
GET /ip/8.8.8.8?deep=true

The second call keeps the core IP fields and, on a paid plan, adds details such as datacenter, relay, and tor inside deep. Code that reads country doesn't have to change. New code can read deep.datacenter when it needs that information.

What an empty deep object means

Without ?deep=true, the response leaves deep out. If you ask but your plan doesn't unlock the detail, it returns deep: {}. Endpoints that have nothing extra to add use the same empty object when asked. A populated deep response can still contain null values when a particular detail is unknown.

The response convention is shared, but access and pricing depend on the endpoint. IP enrichment is included with paid plans. Phone's state and timezone detail and Time's optional detail are included on every plan with the ordinary request. Email deliverability uses a separate verification allowance, including an allowance on Free. The parameter asks for the detail. It doesn't change your plan.

Check the endpoint reference before making a feature depend on a particular deep field. An empty object means there is no detail in this response. A null field inside a populated object means that specific value is unknown. Your interface may need a different explanation for each case.

The point is that extra information has somewhere to go without rearranging the fields you've already built around. You can start with the core response and add the deeper checks where your app needs them.