I'm building a new extension using civix and buildkit. I need to create a new ContactType (sub-type of individual) on install (if it doesn't already exist). I know how I would do it, but I'd prefer to do it in accordance with CiviCRM's standards. What's the correct way to do this?
A contact subtype is an "entity" - it exists as a record in the civicrm_contact_type table. So that means you can use the "managed entity" approach described here:
and documented here:
You could instead implement the install hook (https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install/) and manually test for the existence of the contact type and create it if not (more details in Demerit's answer below).
If you mean which api functions to call to create/update/delete the type, as a general rule you look in api explorer (available via the admin menu in civicrm under Support -> Developer) to see if there's something there (which shows there is ContactType -> create), and if had turned out there wasn't anything you could look in the core code to see how civi does it when you do it from the UI.
If you're asking which hooks to use it would be hook_civicrm_install / uninstall / enable / disable. In install/uninstall you create/delete the type, in enable/disable you set
is_active to 1 or 0. In uninstall you might not want to delete the type if there are existing contacts with that type.