How to load configuration from custom meta data

Custom Metadata isn't just a drop-in configuration load/save system. It acts in most cases like other metadata objects and variables in Apex and is subject to exactly the same syntax and limitations. Most of the issues you have below have to do with Apex and SOQL syntax, rather than Custom Metadata as such.

If the API name of your Custom Metadata record is Thing_REST__mdt, you must always refer to it as such. If you're maintaining more than one configuration, and a single record defines a configuration, you can populate the name of that configuration (such as Thing_REST_stable) in the record's DeveloperName field, and then query based on that field to access a specific configuration.


Thing_REST_stable config;
System.debug('config : ' + config);

This is an uninitialized variable, and like any other in Apex is null. Thing_REST_stable isn't the name of the metadata record, but might be the name of a specific configuration (as above).

Thing_REST__mdt config = new Thing_REST_stable();
System.debug('config : ' + config);

Custom metadata objects instantiated in code are blank, much like sObjects. Custom metadata classes do not have static methods like Custom Settings that instantiate them for you. You'll get a syntax error here because Thing_REST_stable and Thing_REST__mdt aren't the same types.

Thing_REST__mdt[] conf = [SELECT * FROM Thing_REST_stable];
System.debug('config : ' + config);

This is closest to being correct, but SELECT * is not valid SOQL, and you must use the full name of your object (Thing_REST__mdt) in your FROM clause. You might do

Thing_REST__mdt[] conf = [SELECT My_Field__c, My_Preference__c FROM Thing_REST__mdt WHERE DeveloperName = 'Thing_REST_stable'];

to source two specific fields from a defined configuration.

Thing_REST__mdt config = new Thing_REST__mdt();
System.debug('config : ' + config);

This is the same as the one above, but it's closer to being valid because you use your object's API name Thing_REST__mdt in both locations.

Storing Credentials

The best place to store credentials in Salesforce is not Custom Metadata, which can be read by anyone who has View Setup and Configuration permission. It's a Named Credential, which securely protects the credentials and handles OAuth authentication for you.

Custom Metadata and Custom Settings records can only be secured from users and system administrators in the context of a Managed Package, where they can be set to Protected.

You can query custom metadata records with a simple SOQL and here is the syntax -

SELECT (ALL FIELDS WITH COMMA SEPARATED) FROM Thing_REST__mdt WHERE DeveloperName = '*metadata_record_developer_name*'

You can not use * like sql syntax. You have to provide all fields API names in the query.

Example :

String devName = 'Thing_REST_stable';

Thing_REST__mdt  thingsRestSetting = [ SELECT MasterLabel, DeveloperName FROM Thing_REST__mdt WHERE DeveloperName =:devName ];

You can pass the record developer name in the devName variable based on your environment. If the environment is testing then devName will be set to "Thing_REST_latest".

You can learn more about custom metadata from here.