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. Email deliverability uses a separate verification allowance, including an allowance on Free. The parameter asks for the detail. It doesn't change your plan.

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.