There are a few ways to do it, depending on the application. You can attach dataobjects to pages with a relation. The dataobjects would then be edited via a tab on the specific page in the CMS

But you don't necessarily need a custom page type - just to confuse things 🙂 If all you're doing (for example) is returning JSON, then you don't need the custom page type. You can just specify a manual route to the controller and bingo!

In the case of making an API, you'll almost certainly need a custom controller

SilverStripe does a bit of automagic matching in the absence of other directives, so MyPage class would get matched with MyPageController

You can extend the base PageController class if you need to, to provide specific functionality for your new page type (edited)

If you want to create a new page type, you can extend the base Page class. This will give you a new page type that will, by default, be rendered with the base PageController class

SilverStripe suggests a separation of concerns as you'd expect: Your DataObject subclass deals with the data, your Controller subclass deals with the request and response.

As I say, if you're just looking for a simple way to expose your data, the restful module might do all you need.