Cannot get transient to work on shortcode, Moz API

You need to return $seo_grade outside the if i.e. at the very end of your function – at the moment you’re saying “if no transient, create one and return it, otherwise return nothing”.

Also at the top, you return $seo_grade if the domain is "NULL", but the variable will be undefined (possible typo – you’re checking domain is a string called “NULL”, not actually null).

function moz_score_shortcode($atts) {
    extract(
        shortcode_atts(
            array(
                'domain' => '',
            ),
            $atts
        )
    );

    if ( ! $domain )
        return; // No domain, nothing to return

    $cache_key = 'agency_moz_score_' . $domain;

    if ( false === $seo_grade = get_transient( $cache_key ) ) {
        // Setting Moz API connection
        $accessID = "{my api name is here}";
        $secretKey = "{my api password is here}";
        $expires = time() + 300;
        $SignInStr = $accessID. "\n" .$expires;
        $binarySignature = hash_hmac('sha1', $SignInStr, $secretKey, true);
        $SafeSignature = urlencode(base64_encode($binarySignature));
        // Connecting to Moz API url
        $reqUrl = "http://lsapi.seomoz.com/linkscape/url-metrics/".urlencode($domain)."?Cols=103079215108&AccessID=".$accessID."&Expires=".$expires."&Signature=".$SafeSignature;
        // Send request with curl
        $opts = array(
            CURLOPT_RETURNTRANSFER => true
        );
        $curlhandle = curl_init($reqUrl);
        curl_setopt_array($curlhandle, $opts);
        $content = curl_exec($curlhandle);
        curl_close($curlhandle);

        // Getting 'pda' from Moz API and then rounding
        $resObj = json_decode($content);
        $seo_grade = $resObj->pda;
        $seo_grade = round($seo_grade, 0);

        set_transient( $cache_key, $seo_grade );
    }

    return $seo_grade;
}

add_shortcode( 'moz_score','moz_score_shortcode' );