Is there a civi way to manage API compatibility across CiviCRM versions?
When you call an API, Civi does a search to locate it. That typically means searching the PHP include_path for a file named api/v3/{$entity}/{$action}.php or api/v3/{$entity}.php. The include_path is typically managed via hook_civicrm_config.

It sounds like want to change hook_civicrm_config so that the effect is:


Add /path/to/org.example.myext/ to the include_path unconditionally. This contains all you're normal/common files.
Add /path/to/org.example.myext/backports to the include_path if it's an old version (4.6). This contains only the backports/polyfills for older versions.


In most civix-based extensions, it does the first automatically with this snippet:

function {myext}_civicrm_config(&amp;$config) {
  _{myext}_civix_civicrm_config($config);
}


The _{myext}_civix_civicrm_config() is a baseline/default implementation that unconditionally adds /path/to/org.example.myext/ to the include_path. Take a look at the code in _{myext}_civix_civicrm_config($config) to see how it works.

Then you can write a similar function to add /path/to/org.example.myext/backports. Finally, call it:

function {myext}_civicrm_config(&amp;$config) {
  _{myext}_civix_civicrm_config($config)
  if (version_compare(CRM_Utils_System::version(), '4.7', '&lt;')) {
    _{myext}_config_backports($config);
  }
}

function _{myext}_config_backports(&amp;$config) {
  ...
}